简体   繁体   English

尝试释放内存时出现分段错误

[英]Segmentation fault when trying to free memory

I have below code where I have commented when I get segmentation fault and when not. 我有下面的代码,当我得到分段错误时,我已经评论过。

Originally I got segmentation fault and then I could figure out that probably I cannot initialize my char pointer locations like "abcd" . 最初我得到了分段错误然后我可以弄清楚可能我不能初始化我的char指针位置,如"abcd" But I am not able to understand - WHY? 但我无法理解 - 为什么?

I thought testString = "abcd"; 我以为testString = "abcd"; will put a at first memory address, b at second and so on ... 将把a在第一存储器地址, b在第二等等...

Segmentation fault occurs when trying to free memory, based on how I initialize memory location. 根据我初始化内存位置的方式,尝试释放内存时会发生分段错误。

#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);
}


Based on @MM and @Jonathan's comment I understood that with testString = "abcd"; 根据@MM和@ Jonathan的评论,我理解使用testString = "abcd"; my testString will point to a memory location where string "abcd" was created and since I didn't malloc'ed it I cannot free it. 我的testString将指向一个内存位置,其中创建了字符串“abcd”,因为我没有malloc'ed它我无法释放它。 Also, since my original pointer to heap memory (which I got using malloc) is gone, so it is waste of memory or memory lead. 此外,由于我原来的堆内存指针(我使用malloc)已经不见了,所以浪费了内存或内存。

So, does it means that when I use printf statement like printf("Printing character...\\n"); 那么,这是否意味着当我使用像printf("Printing character...\\n");这样的printf("Printing character...\\n");语句时printf("Printing character...\\n"); , this is also a memory leak? ,这也是内存泄漏? Then how do I avoid it? 那我该怎么避免呢? Looping and inserting into char* is certainly a bad idea. 循环和插入char *当然是个坏主意。

this line: 这一行:

testString = "abcd";

is overlaying the pointer given by the call to malloc() with the address of the string literal: "abcd" this results in a memory leak because the original pointer to the allocated memory is lost. 将调用malloc()给出的指针与字符串文字的地址重叠: "abcd"这会导致内存泄漏,因为指向已分配内存的原始指针会丢失。

In C, when copying a string, it 'should' be handled by the functions: strcpy() and strncpy() which will not corrupt the pointer contained in testString . 在C中,当复制字符串时,它应该由函数处理: strcpy()strncpy() ,它们不会破坏testString包含的指针。

strcpy( testString, "abcd" );
strncpy( testString, "abcd", strlen( "abcd" ) );

Naturally, once the pointer to the allocated memory has been overlayed/destroyed by the assignment statement: testString = "abcd"; 当然,一旦指向已分配内存的指针被赋值语句覆盖/销毁: testString = "abcd"; , the new value placed into testString must not be passed to free() ,放入testString的新值不能传递给free()

the seg fault would be happening at the call to free() , not at the incorrect assignment of a new pointer to testString . 在调用free()会发生seg错误,而不是错误地分配一个指向testString的新指针。

Using printf is not a memory leak. 使用printf 不是内存泄漏。 Memory leaks occur when a pointer is allocated via malloc [or, herein, strdup ] and there is no corresponding free call for it. 当通过malloc [或此处strdup ]分配指针并且没有相应的free调用时,会发生内存泄漏。

Also, trying to free a pointer that has not been allocated is another type of error. 此外,试图释放尚未分配的指针是另一种类型的错误。 It [probably] won't segfault, but free will complain. 它[可能]不会是段错误,但是free会抱怨。

Here's a simplified version of your program that illustrates some of the ways you can do this: 这是您的程序的简化版本,它说明了您可以执行此操作的一些方法:

#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;
}

You can run the program with -s to simulate the string constant modification that caused your segfault. 您可以使用-s运行程序来模拟导致segfault的字符串常量修改。

This question has content relevant to answer of my question but doesn't have detailed answer. 这个问题的内容与我的问题的答案有关,但没有详细的答案。 @Jonathan's comments answers all my questions but he hasn't put forward a detailed answer so I am writing my answer so that folks who will visit further can have detailed explanation: @ Jonathan的评论回答了我的所有问题,但他没有提出详细的答案,所以我正在写我的答案,以便进一步访问的人可以得到详细的解释:

I created a pointer and allocated some space on "heap segment" of the memory , now my pointer was pointing to that memory location on heap. 我创建了一个指针,并在内存的“堆段”上分配了一些空间,现在我的指针指向堆上的内存位置。
Code relevant for all this is - char* testString = malloc(sizeof(char) * 5); 与此相关的代码是 - char* testString = malloc(sizeof(char) * 5); .

Now, when I dis this - testString = "abcd"; 现在,当我解除这个 - testString = "abcd"; then string "abcd" is created in "text/code segment" (or in some implementation data segment) of the memory and memory address is returned and assigned to my pointer testString . 然后在内存的“文本/代码段” (或某些实现数据段)中创建字符串“abcd”,并返回内存地址并将其分配给我的指针testString
What happens is that my original pointer which was pointing a memory location on heap is lost and the pointer started pointing to a memory location on text/code segment of the memory. 发生的事情是我的原始指针指向堆上的内存位置,并且指针开始指向内存的文本/代码段上的内存位置。

Implication of all this: 所有这些的含义:

  • It has resulted in memory leak because my original pointer which was pointing to the heap memory is lost, so now I have no way to free that heap memory and hence memory leak. 它导致内存泄漏,因为我指向堆内存的原始指针丢失了,所以现在我无法释放堆内存 ,从而导致内存泄漏。
  • When I will try to free that memory using free(testString); 当我尝试使用free(testString);释放内存时free(testString); then I will get segmentation fault ( this is exactly what has happened to me ) because free() can only be used to free the memory which is allocated using either malloc, calloc or realloc. 然后我会得到分段错误( 这正是发生在我身上的事情 )因为free()只能用来释放使用malloc,calloc或realloc分配的内存。 Now, since the pointer testString is pointing to a memory location on text/code segment and I had not allocated that memory using some C memory allocation method, so I cannot free it using free() and if I do so then I get segmentation fault. 现在,由于指针testString指向文本/代码段上的内存位置,并且我没有使用一些C内存分配方法分配该内存,所以我无法使用free()释放它,如果我这样做,那么我会得到分段错误。
  • When I do testString = "abcd" (when testString is a pointer) then I cannot access the memory location pointed by testString because the memory allocated is read-only in text/code segment of the memory. 当我testString = "abcd" (当的TestString是一个指针),那么我不能访问由指向的存储器位置testString因为分配的内存为只读存储器的文本/代码段。 So, testString[0] = 'x' will also result in segmentation fault. 因此, testString[0] = 'x'也会导致分段错误。

What happens when I do printf("hello, world") ?: 当我做printf("hello, world")时会发生什么?
This will create "hello, world" string as read-only in text/code segment of memory. 这将在内存的文本/代码段中创建“hello,world”字符串为只读。 I verified that it does create in text/code segment in C99 implementation using size command. 我确认它确实使用size命令在C99实现中的文本/代码段中创建。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM