我试图使用动态内存分配与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++) {
niceRows
是float **
,即地址。它的大小在32位系统上是4,在64位系统上是8,但绝对不是你想要的。
应该是for (int i=0; i<3; i++) {
但是这里不需要float **
: float *
就足够了。
你的配置应该是:
float **stop = malloc(3 * sizeof *stop);
malloc
获取的字节数,可以通过sizeof
获得。这是C语言在memcpy
、memset
、fwrite
、qsort
和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
运算符