如何解决malloc()损坏指针的情况?

如何解决malloc()损坏指针的情况?,c,memory,pointers,malloc,corruption,C,Memory,Pointers,Malloc,Corruption,这是我刚才写的一个函数的简化版本: int foobar(char * foo) { puts(type); struct node * ptr = (struct node *) malloc (sizeof(struct node)); puts(type); memset(ptr, 0, sizeof(ptr)); ptr=head; return head->id; } 这里的node只是一个在链接列表中声明为节点的结构,它包含一个char*和一个指向下一

这是我刚才写的一个函数的简化版本:

int foobar(char * foo) {
  puts(type);
  struct node * ptr = (struct node *) malloc (sizeof(struct node));
  puts(type);
  memset(ptr, 0, sizeof(ptr));
  ptr=head;
  return head->id;
}
这里的
node
只是一个在链接列表中声明为节点的结构,它包含一个
char*
和一个指向下一个节点的指针。然而,我意识到这里的
malloc()
正在破坏我的输入
char*foo

为什么
malloc()
会损坏我的输入字符指针?还有,我如何解决这个问题?现在我只是将指针的内容复制到一个本地数组,但这太粗糙了,即使对我来说(这不是最好的)

谢谢你的意见

编辑:这里有更真实的代码:

void foobar(char * type) {
  puts(type); <-- here it's a long string about 30 char
  struct node * ptr = (struct node *) malloc (sizeof(struct node));
  puts(type); <- chopped of, 10 left with some random thing at the end
}

谢谢

发生明显的损坏是因为
type
foo
指向已释放的内存,而
malloc()
会将这些内存返回给您以供不同的使用

一旦释放内存,就无法继续使用它

您还有一个问题,因为您分配给
ptr
,然后用以下命令清除
ptr

ptr = head;
你的意思可能是:

head = ptr;
但是您可能需要设置
ptr->next=head在此之前。当然,这是推测,因为您没有显示类型定义

也不清楚为什么返回
head->id
,而不是
head
ptr
。不幸的是,我们没有足够的信息说“这是错误的”;这是不寻常的


第二版评论 下面是初始化类型的方式:

type = strdup("Some ");
tempType = strdup("things");
sprintf(type + strlen(type), "%s", tempType);
有一些麻烦。你践踏了你不该践踏的记忆

前两行很好;你复制了一个字符串。但是请注意,
type
是指向6字节内存的指针,
testype
是指向7字节内存的指针

灾难发生在第三行

type+strlen(type)
指向
type
字符串末尾的空字节。然后,您或多或少合法地在其上写入1个字节的
testype
;您不再有以null结尾的字符串,但第一个字节在范围内。第二个字节和后续字节写入未分配给您的空间,该空间可能包含有关内存分配的控制信息

写入超出分配内存的界限会导致“未定义的行为”。任何事情都有可能发生。在某些机器上,特别是使用64位编译时,您可能完全不受影响。在大多数机器上,尤其是在32位编译中,您已经破坏了堆内存,因此某些地方(通常离此点有点远)会遇到麻烦。这就是记忆滥用的本质;它发生的地方似乎经常起作用,而另一段无辜的代码却受到其他地方引起的问题的影响

因此,如果要连接这些字符串,需要执行以下操作:

char *type = strdup("Some ");
char *tempType = strdup("things");
char *concat = malloc(strlen(type) + strlen(tempType) + 1);
sprintf(concat, "%s%s", type, tempType);
我忽略了错误检查。您应该检查
strdup()
malloc()
中的分配,以确保已分配内存。有些人可能会认为应该使用
snprintf()
;不这样做是一个有意识的决定,因为我在前一行计算了必要的空间并分配了足够的空间。但你至少应该考虑一下。如果未确保有足够的可用空间,则应使用
snprintf()
避免缓冲区溢出。您还将检查其返回值,以便知道信息是否全部格式化。(还要注意,您有3个指针要释放,或者传递到其他代码,以便在适当的时间释放分配的内存。)


请注意,在Windows上,
snprintf()
(或
\u snprintf()
)的行为不符合C99标准规定的方式。坦率地说,这没有什么帮助。

我不确定你想做什么,但评论表明发生了什么:

// This allocates enough memory for a struct node and assigns it to ptr.
struct node * ptr = (struct node *) malloc (sizeof(struct node));

// This displays the data in the (unspecified) string type,
// which must be null terminated.
puts(type);

// This sets the first 4 bytes of ptr to 0, assuming pointers are 4 bytes.
// You probably want memset(ptr, 0, sizeof(struct node));
memset(ptr, 0, sizeof(ptr));

// This makes ptr point to the address of head, orphaning the memory
// that was just malloc'ed to ptr.
ptr=head;

类型
来自哪里?这是您构造用来存储
foo
的本地数组吗?您的原始代码是否调用了
put(foo)
在添加
类型之前
?您不应该从
malloc(3)
中强制转换返回值,因为包含
stdlib.h
头将提供一个原型,因此编译器将能够为您执行类型检查——当您强制转换返回值时,你可能在掩盖一个可能指示错误代码的警告。为什么你认为
malloc
是罪魁祸首?我们没有足够的信息得出这个结论,也无法回答这个问题。@AaronDufour:char指针在malloc()之前没有问题,但在malloc()之后损坏了。我试着把它打印出来,结果显示出来了,但我可能错了。@sarnold:谢谢!我试试看。你能解释一下它是怎么发生的吗?听起来不是理性的char*foo在堆栈上,malloc在堆上。谢谢,我们看不出麻烦在哪里;它不在显示的代码中。但在分配数据时获得“损坏”的标准方法是使用指向释放内存的指针。另一种引起问题的方法是释放一个指针,该指针实际上不是通过
malloc()
分配的,而是指向堆栈,甚至指向程序的静态数据区(
.data
.bss
段);但通常情况下,这会导致核心转储,而不仅仅是腐败。对于这个问题,这只是稍微简化了一点。我会尽量编辑它,以便更好地显示我的问题。@ZiyaoWei:知道从一个更大的程序中删除多少内容来呈现这样的问题,总是一件棘手的事情。理想的方案是一个大约10-40行的程序,仍然可以重现这个问题。它将是不寻常的,能够得到小于10线;你不想做得太大,尽管有时这是必要的。谢谢我并没有完全预料到仅仅这些w
// This allocates enough memory for a struct node and assigns it to ptr.
struct node * ptr = (struct node *) malloc (sizeof(struct node));

// This displays the data in the (unspecified) string type,
// which must be null terminated.
puts(type);

// This sets the first 4 bytes of ptr to 0, assuming pointers are 4 bytes.
// You probably want memset(ptr, 0, sizeof(struct node));
memset(ptr, 0, sizeof(ptr));

// This makes ptr point to the address of head, orphaning the memory
// that was just malloc'ed to ptr.
ptr=head;