[英]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.