[英]Segmentation fault when trying to free memory
我有下面的代码,当我得到分段错误时,我已经评论过。
最初我得到了分段错误然后我可以弄清楚可能我不能初始化我的char指针位置,如"abcd"
。 但我无法理解 - 为什么?
我以为testString = "abcd";
将把a
在第一存储器地址, b
在第二等等...
根据我初始化内存位置的方式,尝试释放内存时会发生分段错误。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* testString = malloc(sizeof(char) * 5);
printf("Size of char is: %d\n", sizeof(char));
printf("Size of int is: %d\n", sizeof(int));
for(int i = 0; i < 5; i++)
{
printf("Pointer addresses are: %p\n", testString + i);
}
char* tempPtr = testString + 2;
printf("My temp pointer address = %p\n", tempPtr);
// This gives me segmentation fault ....
testString = "abcd";
// This will not give me segmentation fault ....
//int count = 65;
//for(int i = 0; i < 5; i++)
//{
// testString[i] = count + i;
//}
printf("Printing character...\n");
for(int i = 0; i < 5; i++)
{
printf("Characters are: %c\n", testString[i]);
}
printf("Freeing memory...\n");
free(testString);
//printf("Access after freeing >>%c<<\n", tempPtr[0]);
//free(testString);
}
根据@MM和@ Jonathan的评论,我理解使用testString = "abcd";
我的testString
将指向一个内存位置,其中创建了字符串“abcd”,因为我没有malloc'ed它我无法释放它。 此外,由于我原来的堆内存指针(我使用malloc)已经不见了,所以浪费了内存或内存。
那么,这是否意味着当我使用像printf("Printing character...\\n");
这样的printf("Printing character...\\n");
语句时printf("Printing character...\\n");
,这也是内存泄漏? 那我该怎么避免呢? 循环和插入char *当然是个坏主意。
这一行:
testString = "abcd";
将调用malloc()
给出的指针与字符串文字的地址重叠: "abcd"
这会导致内存泄漏,因为指向已分配内存的原始指针会丢失。
在C中,当复制字符串时,它应该由函数处理: strcpy()
和strncpy()
,它们不会破坏testString
包含的指针。
strcpy( testString, "abcd" );
strncpy( testString, "abcd", strlen( "abcd" ) );
当然,一旦指向已分配内存的指针被赋值语句覆盖/销毁: testString = "abcd";
,放入testString
的新值不能传递给free()
在调用free()
会发生seg错误,而不是错误地分配一个指向testString
的新指针。
使用printf
不是内存泄漏。 当通过malloc
[或此处strdup
]分配指针并且没有相应的free
调用时,会发生内存泄漏。
此外,试图释放尚未分配的指针是另一种类型的错误。 它[可能]不会是段错误,但是free
会抱怨。
这是您的程序的简化版本,它说明了您可以执行此操作的一些方法:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
int opt_segv;
char *temp = "abcd";
void
dostr(char *str,int modflg)
{
printf("\n");
printf("dostr: %s\n",str);
if (modflg)
str[modflg] = 'm';
printf("dostr: %s\n",str);
}
void
test1(void)
{
int len;
char *testString;
len = strlen(temp);
testString = malloc(len + 1);
strcpy(testString,temp);
dostr(testString,1);
free(testString);
}
void
test2(void)
{
char *testString;
testString = strdup(temp);
dostr(testString,2);
free(testString);
}
void
test3(void)
{
char *testString;
// passing a pointer to a string _constant_ -- do _not_ modify
testString = temp;
dostr(testString,opt_segv ? 3 : 0);
}
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 's': // generate segfault
opt_segv = 1;
break;
}
}
test1();
test2();
test3();
return 0;
}
您可以使用-s
运行程序来模拟导致segfault的字符串常量修改。
这个问题的内容与我的问题的答案有关,但没有详细的答案。 @ Jonathan的评论回答了我的所有问题,但他没有提出详细的答案,所以我正在写我的答案,以便进一步访问的人可以得到详细的解释:
我创建了一个指针,并在内存的“堆段”上分配了一些空间,现在我的指针指向堆上的内存位置。
与此相关的代码是 - char* testString = malloc(sizeof(char) * 5);
。
现在,当我解除这个 - testString = "abcd";
然后在内存的“文本/代码段” (或某些实现数据段)中创建字符串“abcd”,并返回内存地址并将其分配给我的指针testString
。
发生的事情是我的原始指针指向堆上的内存位置,并且指针开始指向内存的文本/代码段上的内存位置。
所有这些的含义:
free(testString);
释放内存时free(testString);
然后我会得到分段错误( 这正是发生在我身上的事情 )因为free()
只能用来释放使用malloc,calloc或realloc分配的内存。 现在,由于指针testString
指向文本/代码段上的内存位置,并且我没有使用一些C内存分配方法分配该内存,所以我无法使用free()
释放它,如果我这样做,那么我会得到分段错误。 testString = "abcd"
(当的TestString是一个指针),那么我不能访问由指向的存储器位置testString
因为分配的内存为只读存储器的文本/代码段。 因此, testString[0] = 'x'
也会导致分段错误。 当我做printf("hello, world")
时会发生什么?
这将在内存的文本/代码段中创建“hello,world”字符串为只读。 我确认它确实使用size
命令在C99实现中的文本/代码段中创建。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.