簡體   English   中英

嘗試釋放內存時出現分段錯誤

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM