【问题标题】:C: Core dumped with realloc()C:使用 realloc() 转储的核心
【发布时间】:2015-11-18 09:49:36
【问题描述】:

在开始之前,我应该说我已经看过几个关于这个主题的帖子(比如this one,但我仍然缺少一些东西。我对 C 很陌生,所以请多多包涵。我正在尝试构建一个函数将字符串从一个指针位置复制到另一个位置。

#include <stdio.h>
#include <malloc.h>
#include <string.h>

void astrncpy(char **base, char *copyme){

    printf("Copying '%s' into a location currently featuring the following string: '%s'\n", copyme,*base);
    printf("The location of our string to be copied (%s) is %d.\n", copyme, &copyme);
    printf("The location of our string to be replaced (%s) is %d.\n", *base, base);

    //Declare string length variable
    int new_len=strlen(copyme);
    printf("Calculating new length for replaced memory allocation (%d).\n",new_len);

    //Reallocate pointer array
    *base=realloc(*base,sizeof(char)*new_len+1);
    printf("Reallocating memory allocation.\n");

    //Copy copyme content to base string location
    strncpy(*base,copyme,new_len);

    printf("The string at location %d is now %s\n", base, *base);

}

void main(){

    //Declare iterator
    int i;

    //Generate strings
    char first_lit[]="Fortran?";
    char second[]="Now that's a name I've not heard in a long time.";

    //Convert first string to array (so we can get at the pointer to the strings pointer)
    char **first; //Declare pointer to pointer array that represents the first string
    first=malloc(strlen(first_lit)*sizeof(char)); //Allocate space for the pointer array
    *first=first_lit; //Assign values to the pointer locations

    //Copy copyme into base
    astrncpy(first,second);
}

当我尝试在astrncpy() 内重新分配时,核心转储。据我了解,如果指针数组不是 NULL,或者不是malloc() 的乘积,就会发生这种情况。我觉得我没有通过那次测试。任何有关正在发生的事情的指导将不胜感激。

对我构建输入 *base 的见解的奖励积分。我花了很多时间尝试确定**base 参数的可接受输入是什么(注意astrncpy() 的两个参数都在我正在处理的文本中给出)。但是,我不清楚为什么我不能使用first_lit 而不是必须构造first。字符串仍然是一个数组,不是吗?再次感谢您的帮助。

更新:我搁置了一段时间来做我实际上得到报酬的工作,但回到它,我无法动摇以下响应中的声明修改的想法没有必要。 (这是因为它们尚未包含在文本中。)无论如何,我仍然会对解决方案进行检查,因为它有效并且在多个方面都有帮助。但是,应该注意的是,以下方法也有效:

/*Program demonstrates string manipulation operations*/

#include <stdio.h>
#include <malloc.h>
#include <string.h>

void astrncpy(char **base, char *copyme){

    printf("\nWe are inside the function, astrncpy.\n");
    printf("\nCopying '%s' (*copyme) into a location currently featuring the following string: '%s' (**base)\n", copyme,*base);
    printf("The location of our string to be copied (%s) is %p.\n", copyme, &copyme);
    printf("The location of our string to be replaced (%s) is %p.\n", *base, base);

    //Declare string length variable
    size_t new_len=strlen(copyme);
    printf("Calculating new length for replaced memory allocation (%d).\n",new_len);

    //Reallocate pointer array
    printf("Reallocating memory block associated with base string to be replaced.\n");
    *base=realloc(*base,sizeof(char)*(new_len+1));


    //Copy copyme content to base string location
    strncpy(*base,copyme,new_len);

    printf("The string at location %p is now %s\n", base, *base);

}

void main(){

    //Declare iterator
    int i;

    //Generate strings
    char first_lit[]="Fortran?";
    char second[]="Now that's a name I've not heard in a long time.";
    //int testint=5;

    //Capture elements of first_lit in pointer array (so we can get at the pointer to the strings pointer)
    char *first; //Declare pointer to pointer array that represents the first string
    first=malloc((strlen(first_lit)+1)*sizeof(char)); //Allocate space for the pointer array
    strncpy(first,first_lit,strlen(first_lit)); //Assign values to the pointer locations

    //Copy copyme into base
    printf("Initiating copy operation...\n");
    astrncpy(&first,second);
}

【问题讨论】:

  • 您的链接问题有一个答案“唯一可以传递给 realloc 的指针是空指针以及之前由 calloc、malloc 或 realloc 返回的指针!”
  • 注意:这是int main(void) -- C 不是 Java。
  • first=malloc(strlen(first_lit)*sizeof(char)) - 这完全是错误的尺寸计算
  • strncpy(*base,copyme,new_len); - 你忘了空终止字符串。要解决此问题,请使用 strcpy(*base, copyme);strncpy 函数是 strcpy 的不安全版本,应避免使用

标签: c segmentation-fault realloc


【解决方案1】:

看看这些陈述

first=malloc(strlen(first_lit)*sizeof(char)); //Allocate space for the pointer array
*first=first_lit; //Assign values to the pointer locations

您似乎认为您可以将数组与其他数组一起分配。

这是一个错误的假设。您只能将一个数组的元素复制到另一个数组中。

还要考虑到您将函数命名为

astrncpy
    ^^

但通常在中间带有n 的此类函数具有size_t 类型的参数。您的函数没有这样的参数。所以最好把它命名为

astrcpy

即在函数名中间没有n

通常字符串函数也会返回指向目标字符串的指针。

你的意思是如下

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char * astrcpy( char **base, const char *copyme )
{
    printf( "Copying '%s' into a location currently featuring the following string: '%s'\n", copyme,*base );
    printf( "The location of our string to be copied (%s) is %p.\n", copyme, ( const void * )copyme );
    printf( "The location of our string to be replaced (%s) is %p.\n", *base,  ( void * )*base );

    //Declare string length variable
    size_t new_len = strlen( copyme );
    printf("Calculating new length for replaced memory allocation (%zu).\n", new_len );

    //Reallocate pointer array
    printf("Reallocating memory allocation.\n");

    char *tmp;
    if ( ( tmp = realloc( *base, sizeof( char ) * ( new_len + 1 ) ) ) != NULL )
    {
        *base = tmp;

        //Copy copyme content to base string location
        strcpy( *base, copyme );

        printf( "The string at location %p is now %s\n", ( void * )*base, *base );
    }

    return tmp;
}

int main( void )
{
    //Generate strings
    char first_lit[] = "Fortran?";
    char second[] = "Now that's a name I've not heard in a long time.";

    //Convert first string to array (so we can get at the pointer to the strings pointer)
    char *first; //Declare pointer to pointer array that represents the first string

    first = malloc( ( strlen( first_lit ) + 1 ) * sizeof( char ) ); //Allocate space for the pointer array
    strcpy( first, first_lit ); //Assign values to the pointer locations

    //Copy copyme into base
    if ( astrcpy( &first, second ) ) puts( first );

    free( first );
}

程序输出是

Copying 'Now that's a name I've not heard in a long time.' into a location currently featuring the following string: 'Fortran?'
The location of our string to be copied (Now that's a name I've not heard in a long time.) is 0x7ffe4b3d23d0.
The location of our string to be replaced (Fortran?) is 0x6da010.
Calculating new length for replaced memory allocation (48).
Reallocating memory allocation.
The string at location 0x6da010 is now Now that's a name I've not heard in a long time.
Now that's a name I've not heard in a long time.

有趣的是,函数realloc 并没有改变内存的初始地址。它只是放大了它。:)

重新分配之前

The location of our string to be replaced (Fortran?) is 0x6da010.

在重新分配之后

The string at location 0x6da010 is now Now that's a name I've not heard in a long time.

地址相同0x6da010

至于这个问题

但是,我不清楚为什么我不能使用 first_lit 而不必先构建

那么您不能移动具有静态或自动存储持续时间的数组。您只能重新分配动态分配的内存并在那里复制一个数组。

因此,您不能为 first_lit 重新分配内存。您可以动态分配内存并复制数组first_lit 的元素,然后您可以重新分配这个动态分配的内存。

【讨论】:

  • 有很多有用的信息。感谢所有人(认真地),但这个回复是最全面的。不过,在我检查它之前,我有几个问题。首先,在将静态存储数组分配给动态数组时,目标动态数组的大小能否超过源数组?其次,我不知道size_t 内在,但为什么int 不够?另外,感谢有关在函数名称中使用 n 的信息。它来自文本,但很高兴知道。最后,我可以发誓我尝试了char *first/astrncpy(&amp;first...) 组合,但我会再试一次。
  • @Marvin Ward Jr 您可以将存储在一个较小数组中的字符串复制到一个较大数组中。函数 strlen 允许确定数组中的字符串使用了多少元素。 size_t 是实现定义的无符号整数类型。此类型由运算符 sizeof 和函数 strlen 返回。所以最好使用那个尺寸。至于最后一个问题那我没看懂..
  • 别担心,最后一个不是问题,而是参考我尝试将**base 输入到atrscpy() 中的工作。无论如何,您为什么使用(void *) 而不是&amp;?它似乎具有相同的效果,并且在某些地方似乎没有必要。 (程序使用(void *)*basebase 运行。)它似乎唯一重要的地方是当const 调用发挥作用时(const void *) copyme。没有const 我有一个段错误。它是否正确假设发生了一些修改 copyme 指针的工作?再次感谢您的所有帮助。
【解决方案2】:

根据C11 标准,第 7.22.3.5 章,realloc() 规范,(强调我的

void *realloc(void *ptr, size_t size);

如果ptr 是空指针,则realloc() 函数的行为类似于指定sizemalloc() 函数。否则,如果ptr 与内存管理函数先前返回的指针不匹配,或者如果空间已通过调用free()realloc() 函数被释放,行为未定义。 [...]

在您的情况下,*base 不是malloc() 和家人返回的指针。因此undefined behavior。分段错误随之而来。

也就是说,在main() 内部,first 的分配看起来也有问题。 firstchar ** 的内存分配应该是这样的

first = malloc(sizeof(*first) * num_of_pointers_needed);

而不是

first=malloc(strlen(first_lit)*sizeof(char));

另外,在使用返回的指针之前,您应该始终检查malloc() 和family 的返回值是否为NULL,以确保成功。

最后,一个类似的语法

 p = realloc(p, newsize);

非常危险,因为如果realloc() 失败,您最终会通过将realloc()return 值分配给同一指针而丢失实际指针。再次引用标准,

[...] 如果新对象的内存不能 已分配,旧对象不会被释放,其值不变。

realloc() 函数返回一个指向新对象的指针(它可能与指向旧对象的指针具有相同的值),如果无法分配新对象,则返回一个空指针。

您应该始终在某个临时指针中收集realloc() 的返回值,执行成功检查并在成功时将其分配回实际指针。

【讨论】:

    【解决方案3】:

    您正在传递指向堆栈中分配的内存的指针,试图重新分配它。这是错误的。你应该首先 malloc() 字符串,然后尝试 realloc() 它。

    【讨论】:

      【解决方案4】:

      据我了解,如果指针数组不是 NULL,或者不是 malloc() 的乘积,就会发生这种情况。

      第一部分是不对的。第二部分是对的。 realloc 的参数可以为 NULL。如果它不为 NULL,则它必须是由malloc 系列函数返回的值。

      您的代码的问题是main 中的*first 不是mallocrealloc 返回的值。它只是一个指向main 中的数组的指针。

      【讨论】:

        猜你喜欢
        • 2015-11-13
        • 1970-01-01
        • 2021-07-19
        • 2019-07-22
        • 1970-01-01
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        • 2021-08-07
        相关资源
        最近更新 更多