【问题标题】:How to use free on a handle inside a list?-> C -> windows API如何在列表内的句柄上使用 free?-> C -> windows API
【发布时间】:2010-12-23 18:53:08
【问题描述】:

我在 C 中有一个类似这样的列表:

typedef struct _node
{
   int number;
   DWORD threadID;
   HANDLE threadH;
   struct *_node next;
} *node;

你有这样的东西:

node new_node = malloc(sizeof(node));

您可能已经猜到了,这个列表将存储线程的信息,包括它们的处理程序和 Id。当我尝试这样做时仍然遇到问题:

free(new_node);

每次我尝试这样做时都会遇到意外错误,VS 说存在数据损坏。我已经尽可能地确定了,当我尝试使用释放手柄时,我发现问题仍然存在。 我已经在 MSDN 上搜索了如何执行此操作,但我唯一能找到的是关闭线程的函数(此处不打算这样做,因为我希望线程运行,只需从列表中删除它的记录)。

问题是:我应该如何从内存中释放句柄? (考虑到这只是句柄值的副本,活动句柄不会被删除)。

编辑:这是从列表中插入节点的函数:

int insereVisitanteLista(node* lista, DWORD threadID, HANDLE threadH, int num_visitante)
{
    node visitanteAnterior;
    node novoVisitante = (node)malloc(sizeof(node));

    if(novoVisitante == NULL)
        return 0;

    novoVisitante->threadID = threadID;
    novoVisitante->threadH = threadH;
    novoVisitante->number = num_visitante;
    novoVisitante->next = NULL;

    if(*lista == NULL)
    {
        *lista = novoVisitante;
        return 1;
    }

    visitanteAnterior = *lista;

    while(visitanteAnterior->next != NULL)
        visitanteAnterior = visitanteAnterior->next;

    visitanteAnterior->next =novoVisitante;
    return 1;
}

这是删除节点的功能:

int removeVisitanteLista(node * lista, DWORD threadID)
{
    node visitanteAnterior = NULL, visitanteActual;

    if(*lista == NULL)
        return 0;

    visitanteActual = *lista;

    if((*lista)->threadID == threadID)
    {
        *lista = visitanteActual->next;
        visitanteActual->next = NULL;
        free(visitanteActual);

        return 1;
    }

    while(visitanteActual != NULL && visitanteActual->threadID != threadID)
    {
        visitanteAnterior = visitanteActual;
        visitanteActual = visitanteActual->next;
    }

    if (visitanteActual == NULL)
        return 0;

    visitanteAnterior->next = visitanteActual->next;
    free(visitanteActual);

    return 1;
}

【问题讨论】:

  • 列表插入/删除代码看起来不错...
  • 我也这么认为....不知道为什么手柄让我这么打架。试图将句柄的指针转换为 void*,没有骰子,将句柄 1st 设置为 null,也没有骰子....我真的没有得到这个......而且插入总是很好,移除永远不会跨度>

标签: c windows memory-management handle memory-corruption


【解决方案1】:

您想要释放的 node 到底是什么?这是指向结构_node 的指针吗?如果是,您之前是否分配过?如果否,则不需要free,否则您必须检查节点是否不是NULL,并确保您没有多次free。如果没有重现问题的最小工作示例,很难猜测您在做什么以及错误在哪里。我唯一能建议的就是阅读 C 中的内存管理。This resource 可能会有所帮助。

更新:

代码中的node 是指向_node 的指针。所以 sizeof (node) 是一个指针的大小,它是 4 或 8 字节(取决于架构)。因此,例如,您分配了 8 个字节,但假设您有一个指向更大的结构的指针。结果,您破坏了内存,并且程序的行为变得不确定。因此,将 node novoVisitante = (node)malloc(sizeof(node)) 更改为 node novoVisitante = (node)malloc(sizeof(_node)) 应该可以解决问题。

【讨论】:

  • 嗯,你是对的,我匆忙发布了这个问题。是的,该节点是一个 *_node ,它之前被 malloc 没有问题(并且正在使用正确的值访问它,我也检查了它)。我只尝试释放一次(从列表中删除一个节点)并在那里得到错误。假设你有类似 _node * node = malloc(sizeof(node)); -> 那些行中的东西
  • 除非malloc 返回NULL,否则free (malloc (sizeof (_node))); 不可能出现此错误。所以那里发生了其他事情,你没有告诉:-)
  • Dunno what is.... BTW 发现了另一条可能有帮助的信息:我检查了 VS 给出的错误,似乎错误是在 void __cdecl _unlock 函数的末尾报告的在 mlock.c 文件中(我相信这与互斥锁、信号量等有关)。当我在排除区域内时删除句柄有问题吗? (仍然没有意义,因为我没有删除句柄本身)。 PS:我没有发布整个代码,因为它非常大,如果不是因为我会立即发布编辑:添加了从列表中添加和删除节点的功能
  • PS:代码翻译可能有语法错误,不要介意,
  • @John:我至少发现了一个重大错误,它肯定会使整个事情崩溃。修复它,如果还有问题,请告诉我。
【解决方案2】:

你没有向我们展示你调用 free() 的上下文,所以我需要推测一下,但我首先担心的是你没有提到在删除节点之前从列表中删除它。

首先通过修改前一个(或头)节点的下一个字段来取消链接节点。如果您仍然收到错误,那么您已经通过写入超过您分配的内存结构之一的末尾或类似的东西以某种方式损坏了内存。

另外,我假设 node 是一个指针。你真的没有提供太多关于你在做什么的信息。

【讨论】:

  • 嗯,你是对的,我匆忙发布了这个问题。是的,该节点是一个 *_node ,它之前被 malloc 没有问题(并且正在使用正确的值访问它,我也检查了它)。我只尝试释放一次(从列表中删除一个节点)并在那里得到错误。
  • 抱歉,我试图更新我的答案并编辑了你的答案 :-)))我要睡觉了...
  • 弗拉德:我试图弄清楚那里发生了什么。 :-)
猜你喜欢
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多