5

我有一个结构

typedef struct my_s {

   int x;
   ...
} my_T;

my_t * p_my_t;

我想设置 to 的地址,p_my_t到目前为止NULL,这就是我尝试这样做的方式:

memset (&p_my_t, 0, sizeof(my_t*))

不过,这对我来说并不合适。这样做的正确方法是什么?


修改问题 - 提出一个更复杂的问题

这是我正在尝试做的事情:

  • 两个进程,A 和 B
  • A、B中的malloc p_my_t有N个线程,可以访问
  • 开始在 A 中删除,但我不能简单地释放它,因为 B 中的线程可能仍在使用它。
  • 所以我调用了一个函数,将 p_my_t 的地址传递给 B 以在 B 中将其地址设置为 NULL,这样 B 中的其他线程就不能再使用了
  • 从 B 回调后,我在 A 中释放内存

注意:没有标准的方法可以通过进程之间的共享内存来管理内存分配。您将不得不对正在发生的事情做一些相当仔细的思考。

4

9 回答 9

21

不要memset用于初始化空指针,因为这会将内存设置为所有位为零,这不能保证是空指针的表示,只需执行以下操作:

p_my_t = NULL;

或等价物:

p_my_t = 0;
于 2008-12-29T22:22:25.753 回答
4

你到底想做什么? p_my_t已经是一个指针,但你还没有为它分配内存。如果要将指针设置为 NULL,只需执行

p_my_t = NULL;

尝试取消引用此指针将导致分段错误(或 Windows 上的访问冲突)。

一旦指针实际指向某物(例如,通过malloc()或通过为其分配 a 的地址struct my_T),那么您可以正确地使用memset()它:

memset(p_my_t, 0, sizeof(struct my_T));

这会将整个结构清零,将所有字段设置为零。

于 2008-12-29T22:22:48.857 回答
2

将指针设置为null的推荐代码是分配 0(零)。Bjarne Stroustrup做到了 :) 无论如何,它与 NULL 一样具有表现力,并且不依赖于宏定义。

请注意,NULL 不是关键字,它不是保留的,虽然重新定义会令人困惑,但没有什么说你不应该(除了风格)。一位同事经常开玩笑说在某些标头中将 NULL 定义为不同于 0 的东西,只是为了看看其他人的代码如何表现。

在即将发布的标准中,将有一个更具表现力的nullptr关键字来标识空指针。

于 2008-12-29T23:02:13.380 回答
2

我想也许你想要

extern void set_t_pointer_to_null(my_T *pp);

并打电话

set_t_pointer_to_null(&p_my_t);

在哪里

void set_t_pointer_to_null(my_T *pp) { *pp = NULL; }

我不确定是否值得定义一个函数来执行此操作,但我认为这回答了您要问的问题。

于 2008-12-30T02:56:05.747 回答
0

如果我做对了,memset 将无法解决您的问题。如果 A 和 B 是单独的进程,那么p_my_t在进程 A 中,进程 B 中的形式将是不同p_my_t的。您只是不能在不同进程之间传递指针。我建议您使用某种 IPC 机制来同步您的两个进程(例如消息队列),并且只使用p_my_t = NULL而不是 memset。

于 2008-12-30T10:50:22.933 回答
0

谢谢,这是我想要做的

  • 两个进程,A 和 B
  • A、B中的malloc p_my_t有N个线程,可以访问
  • 开始在 A 中删除,但我不能简单地释放它,因为 B 中的线程可能仍在使用。
  • 所以我调用了一个函数,将 p_my_t 的地址传递给 B 以在 B 中将其地址设置为 NULL,这样 B 中的其他线程就不能再使用了
  • 从 B 回调后,我在 A 中释放内存
于 2008-12-29T22:39:09.417 回答
0

根据您的回复(在这篇文章的其他地方)说明:

谢谢,这是我想要做的

  • 两个进程,A 和 B
  • A、B中的mallocp_my_t有N个线程,可以访问
  • 开始在 A 中删除,但我不能简单地释放它,因为 B 中的线程可能仍在使用。
  • 所以我调用一个函数,将地址传递p_my_t给 B 以在 B 中将其地址设置为 NULL ,这样 B 中的其他线程就不能再使用了
  • 从 B 回调后,我在 A 中释放内存

您需要的是所有线程和进程之间的某种形式的同步。我不确定您如何在进程之间共享此对象,但我怀疑您正在使用共享内存。

通常我会推荐使用共享指针类(例如 Boost 的shared_ptr类),但我不确定它在这种情况下的效果如何。您可能需要考虑调整您的类,以便它跟踪自己的引用并可以与 Boostintrusive_ptr类一起使用。

这样,进程 A 可以简单地忘记该对象,当进程 B 完成时,实例my_T将知道没有更多的引用,并自行清理。

当在内部添加或删除引用时,同步将在这里发挥作用my_T(因此您不会遇到令人讨厌的竞争条件,它认为它应该自行清理但实际上仍在使用中)。

另一种具有更多“kluge”感觉的方法是给每个实例my_T一个“is-valid”标志,以便所有使用它的进程/线程都知道是否继续这样做。

有关 Boost 各种指针类的更多详细信息,请查看他们的文档

于 2008-12-29T22:48:50.067 回答
0

根据您的更新,在我看来,您真正想做的是保护对资源的访问,这意味着您应该使用进程之间共享的读/写锁来保护该资源的 ptr,并测试ptr 使用前。

  • 在共享内存中分配结构。
  • 将 ptr 分配给共享内存中的结构。
  • 使用读/写锁保护对结构的 ptr 的访问。
  • 进程 A 在初始化或使 ptr 和结构无效时应获取对 ptr 的 WRITE 锁。
  • 进程 B 应该获取对 ptr 的 READ 锁,并在使用结构之前测试 ptr 是否有效
于 2008-12-30T18:43:36.473 回答
0

通过阅读您的多线程评论,我应该说没有安全的代码序列来完成您的任务。您将不得不退后一步重新检查您的算法。

于 2008-12-30T03:44:54.027 回答