Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 结构内部数组的声明有时会失败_C_Arrays_Struct_Segmentation Fault - Fatal编程技术网

C 结构内部数组的声明有时会失败

C 结构内部数组的声明有时会失败,c,arrays,struct,segmentation-fault,C,Arrays,Struct,Segmentation Fault,是什么导致以下代码在某些Linux/gcc环境中失败?我声明一个结构,然后创建这个结构的“实例”。问题在于数组,它应该包含单独的字符串并且可以调整大小。详情: typedef struct { char (*pointer)[256]; int used; int size; } Array; Array *createArray(int start_size) { Array *array = malloc(sizeof( *array)); arra

是什么导致以下代码在某些Linux/gcc环境中失败?我声明一个结构,然后创建这个结构的“实例”。问题在于数组,它应该包含单独的字符串并且可以调整大小。详情:

typedef struct {
    char (*pointer)[256];
    int used;
    int size;
} Array;

Array *createArray(int start_size) {
    Array *array = malloc(sizeof( *array));
    array->used = 0;
    array->size = start_size;
    array->pointer = malloc(start_size * sizeof *array->pointer); // <--- here
    return array;
}

Valgrind显示,上面标有
的行上有一个错误,需要根据Pablo的评论修复
解析
逻辑并改进
realloc
!如上所述,当
malloc
realloc
返回时,检查
NULL

这是一个用于进一步改进的MCVE:

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

#define DEFAULT_SIZE 256

typedef struct {
    char (*pointer)[256];
    int used;
    int size;
} Array;

Array *createArray(int start_size) {
    Array *array = malloc(sizeof(*array));
    array->used = 0;
    array->size = start_size;
    array->pointer = malloc(start_size * sizeof * array->pointer); // 
    return array;
}

void append(Array *array, char* elem) {
    if (array->used >= array->size) {
        // expand table
        array->pointer = realloc(array->pointer, array->size * 2 * sizeof * array->pointer);
        array->size *= 2;
    }
    // append new arg
    strcpy(array->pointer[array->used] , elem); // <-- here
    array->used++;
}


Array *parse(char* command) {
    // split command by space and store each arg in array
    char *args_str;
    Array *args_list = createArray(DEFAULT_SIZE); // expandable array holding arguments

    args_str = strtok(command, " ");

    append(args_list, args_str);

    args_str = strtok(NULL, " ");

    append(args_list, args_str);

    return(args_list);
}

int main(void)
{
    char str[] = { '1', '2', '3', ' ', '5', '6', '7', ' ', 0 };

    Array *p = parse(str);

    printf("%s\n",p->pointer[0]);
    printf("%s\n",p->pointer[1]);

    return 0;
}

我将引用我自己的评论:

在append中,您应该声明char
(*tmp)[256]并像这样调用realloc:
tmp=realloc(数组->指针,…)

然后检查
tmp==NULL
并处理错误情况,如果不是
NULL
array->pointer=tmp。
如果源字符串elem的长度超过255个字符,也可能导致指针溢出,
这将导致未定义的行为。使用

strncpy(array->pointer[array->used] , elem, sizeof *array->pointer[array->used]);
array->pointer[array->used][sizeof(array->pointer[array->used]) - 1] = 0;
相反

append
函数有一个小问题,它不会返回 任何东西我将其修改为:

Array *parse(char* command) {
    // split command by space and store each arg in array
    char *args_str;
    Array *args_list = createArray(DEFAULT_SIZE); // expandable array holding arguments

    args_str = strtok(command, " ");

    do {
        append(args_list, args_str);
    } while(args_str = strtok(NULL, " "));


    return args_list;
}
我获取了您的代码并修复了
parse
函数,并从我的
main
功能

int main(void)
{
    Array *array;
    char cmd[] = "ls -alh --color /tmp";

    array = parse(cmd);

    if(array == NULL)
        return 0;

    printf("Array->used: %d, array->size: %d\n", array->used, array->size);
    for(int i = 0; i < array->used; ++i)
        puts(array->pointer[i]);

    free(array->pointer);
    free(array);
}
代码运行正常,问题可能是由于未定义的 调用
parse
之前的行为。我已将测试代码放在这里:


正如您在ideone上看到的,代码也会产生正确的结果。

问题在于您没有显示的代码。Valgrind告诉你内存分配的位置。它还告诉您在哪里使用了分配给那里的未初始化值。查看该行。请参见@MattS no,
Array*Array=malloc(sizeof(*Array))是正确的
sizeof*array
返回
array
对象需要的字节数
sizeof(array)
返回指向
array
的指针需要存储的字节数。似乎您不理解
malloc
。在
append
中,您应该声明
char(*tmp)[256]
并像这样调用
realloc
tmp=realloc(数组->指针,…)
然后检查
tmp==NULL
并处理错误情况,如果不是
NULL
array->pointer=tmp
;。如果源字符串
elem
长度超过255个字符,也可能导致指针溢出,这将导致未定义的行为。使用
strncpy(数组->指针[数组->使用]、元素、大小*数组->指针[数组->使用];数组->指针[数组->已用][sizeof(数组->指针[数组->已用])-1]=0。@MattS OP正在为维度为256的
数组->大小
数组分配空间。如果OP有
char**指针
,那么OP必须
malloc
大小
array->size*sizeof(char*)
,并且for every
i
必须再次执行
malloc
大小为256的操作。
123
567
strncpy(array->pointer[array->used] , elem, sizeof *array->pointer[array->used]);
array->pointer[array->used][sizeof(array->pointer[array->used]) - 1] = 0;
Array *parse(char* command) {
    // split command by space and store each arg in array
    char *args_str;
    Array *args_list = createArray(DEFAULT_SIZE); // expandable array holding arguments

    args_str = strtok(command, " ");

    do {
        append(args_list, args_str);
    } while(args_str = strtok(NULL, " "));


    return args_list;
}
int main(void)
{
    Array *array;
    char cmd[] = "ls -alh --color /tmp";

    array = parse(cmd);

    if(array == NULL)
        return 0;

    printf("Array->used: %d, array->size: %d\n", array->used, array->size);
    for(int i = 0; i < array->used; ++i)
        puts(array->pointer[i]);

    free(array->pointer);
    free(array);
}