C语言 用二维数组分配内存



我试图使用动态内存分配与2D数组,我似乎不能让我的功能按预期工作。我想把我的函数传递一长串字符,分解并存储某些部分作为单独的字符串(在它们自己的字符数组中),然后将它们添加到2D数组中并返回最后的东西。函数中分割字符串并存储我想要的内容的部分工作得很好。内存分配是我做错的地方。

例如,我将字符串"0,,10000,10000,"Albany Hwy After Armadale Rd",",-32.1479054960,116.0201957650,4"传递给函数,它会取出"10000","-32.1479054960"one_answers"116.0201957650",将它们存储在自己的数组中,然后将它们全部添加到一个名为"stop"的数组中。我(尝试)要做的是为我将存储的3个字符串分配内存,然后当我添加字符串时,我为它们分配内存。

下面是我的函数:

 char **getStopData(char line[]) {
int commas = 0;
int len = strlen(line);
char **stop = malloc(3); //Block of memory for each string
char stop_id[20]; //Temp array to build stop_id string 
char lat[20]; //Temp array to build lat string
char lon[20]; //Temp array to build lon string
int counter;
for(int i = 0; i <len; i++) { 
    if(line[i] == ',')  {
        commas++;
        counter = 0;
        continue;
    }
    switch(commas) { //Build strings here and store them - works fine
        case 2 :
            stop_id[counter++] = line[i]; 
            if(line[i+1] == ',') stop_id[counter] = '';
            break;
        case 6 : 
            lat[counter++] =  line[i]; 
            if(line[i+1] == ',') lat[counter] = '';
            break;
        case 7 : 
            lon[counter++] =  line[i];
            if(line[i+1] == ',') lon[counter] = '';
            break;
    }
}
//Assign memory for each string to be added to 'stop' & add my strings to 'stop'
stop[0] = malloc(sizeof(stop_id));
stop[0] = stop_id;
stop[1] = malloc(sizeof(lat));
stop[1] = lat;
stop[2] = malloc(sizeof(lon));
stop[2] = lon;
return stop;
}

And my main:

int main(int argc, char *argv[]) {
char  **niceRows = getStopData(argv[1]);
for (int i=0; i<sizeof(niceRows); i++) {    
    printf("%dn",*niceRows[i]);
    free(niceRows[i]);
}
free(niceRows);
return 0;
}

当我运行我的函数时,我得到一堆运行时错误与我的内存分配有关。error for object 0x7fff5266bb70: pointer being freed was not allocated set a breakpoint in malloc_error_break to debug

这一行返回一个指向已分配内存的指针

stop[ 0 ] = malloc( sizeof( stop_id ) );

下一行将覆盖,并将指针指向stop_id

stop[0] = stop_id;

stop[1]和stop[2]相同

你想做什么

memcpy( stop[ 0 ], stop_id, 20 );

EDIT (via M Oehm):您还应该更改

char **stop = malloc(3);

char **stop = malloc( 3 * sizeof( char * ) );

你的代码中有一些主要的问题。

float **stop = malloc(3); //Block of memory for each string

只分配3个字节或内存,不够。你应该写:

float **stop = malloc(3 * sizeof(float *)); //Block of memory for each string

因为这将为3 float *分配内存。

之后,您有stop[0] = malloc(sizeof(stop_id));,您分配了20字节的内存,但是您只会在其中写入 float 。你最好这样写:

stop[0] = malloc(sizeof(float));

stop[1]stop[2]相同。

最后是for (int i=0; i<sizeof(niceRows); i++) {

niceRowsfloat **,即地址。它的大小在32位系统上是4,在64位系统上是8,但绝对不是你想要的。

应该是for (int i=0; i<3; i++) {

但是这里不需要float **: float *就足够了。

你的配置应该是:

float **stop = malloc(3 * sizeof *stop);

malloc获取的字节数,可以通过sizeof获得。这是C语言在memcpymemsetfwriteqsort和malloc : You operate on byte memory with ´void *指针等低级函数中迎合任意类型的方式。这会丢失类型信息,但允许您通过使用sizeof(T)指定类型的字节大小来使用任何类型。

(这也容易出错,因为您必须保持数据和类型同步。)

在main中,您尝试使用sizeof:

获取分配的指针-浮点数组的长度。
for (int i = 0; i < sizeof(niceRows); i++) ...

这行不通。niceRows的大小是指针的大小,根据您的系统,它是4或8。

没有办法知道给指针分配了多少内存。您必须将此信息作为单独的值保存。最好的方法是将已分配内存的指针和大小信息捆绑在一个结构体中。

在你的例子中,getStopData总是返回一个包含三个指针的数组来浮动。这里不需要长度信息,但是您可能应该记录返回的数组总是有三个条目的事实。所以:

for (int i = 0; i < 3; i++) ...

比数组更好的设计可能是结构体,其中条目的名称已经告诉您要查看的数据。

最后,您可能应该初始化临时字符缓冲区stop_id, lat和' lon ',以捕获逗号少于7的情况。

  • 使用指针到指针来获得一个2D数组是毫无意义的,这是广泛传播但不正确的,坏的做法。通过

    获取指向动态二维数组的指针
    char (*ptr)[x][y] = malloc(char[x][y]);
    

    或者如果你的编译器是由dinosaurs设计的:

    char* ptr = malloc(sizeof(*ptr) * x * y);
    
  • 在你的特殊情况下,你可能甚至不想要一个2D数组,你想要一个指针数组,每个指针指向一个可变长度的字符串。这样的数组声明为char* stop[3];

  • 在C语言中,不能使用=赋值操作符复制数组。你必须使用memcpy或strcpy

  • 只能对静态分配的数组使用sizeof运算符

最新更新