c - 动态分配多维浮点数组的正确方法是什么? Valgrind 错误
c - Which is the correct way to dynamically allocate multidimensional float arrays? Valgrind error
我正在用 C 实现一个 K-means 算法。它在大多数情况下都运行良好,但是使用 Valgrind 调试它告诉我我正在做一个 "Invalid read of size 8 - Invalid write of size 8 - Invalid read of size 8" 使用 '''memcpy''' 开头。我认为问题不在那里,但我为多维浮点数组元素分配了一个值,该内存在某些时候使用带有 for 循环的“'malloc'”动态分配。因为 Valgrind 也告诉 "Address 0x572c380 is 0 bytes after a block of size 80 alloc'd".
我尝试将我分配的字节数加 1,因为我认为可能“'malloc'”"needed" 更多内存来完成它的工作,但没有任何改变.我知道这可能是一个基本错误,但我对这门语言还很陌生,在我的课程中它没有解释任何东西,所以 "technical"。我试图搜索错误的答案和解释,但我只发现了“'char'”数组的问题,而那些我理解的函数“'strcpy'”可以解决问题。浮点数组呢?这是第一次使用'''memcpy'''。
以下是引发这些 Valgrind 消息的代码片段。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
FILE* fp; //used to open a .txt file to read
char buf[100];
float ** a;
char * s;
int i;
int j;
int rows = 10;
fp = fopen("data.txt", "r");
if(fp==NULL){
perror("Error at open file.");
exit(1);
}
a = (float**) malloc(rows*sizeof(float*));
for(i=0; i<rows; i++){
s = fgets(buf, 100, fp); //reading .txt file
if (s==NULL){
break;
}
a[i] = malloc(dim*sizeof(float));
a[i][0] = atof(strtok(s, ","));
for(j=1; j<dim; j++){
a[i][j] = atof(strtok(NULL,",")); //save as float value the token read from a line in file, for example, from line "1.0,2.0,3.0" as first line -> get a[0][1] = 2.0
}
}
fclose(fp);
m = (float**) malloc(rows*sizeof(float*));
for (i=0; i<rows; i++){
m[i]=malloc(dim*sizeof(float)); //not initialized
}
memcpy(m, a, rows*dim*sizeof(float));
}
有人能帮我理解为什么它有效但 Valgrind 会引发这些错误消息吗?
您首先分配了一个 float*
数组, 然后 分配了多个 float
数组,因此您的最后一个 memcpy(m, a, rows*dim*sizeof(float))
复制了一个数组float*
(指向 float
的指针)指向另一个,但使用 rows * dim
浮点数,@SomeProgrammerDude 正确地指出了这一点。那会复制 pointers,而不是 values.
此外,正如@xing 所指出的,您正在分配 rows
但使用 righe
(您没有显示)。这可能是问题的原因。
我建议在第一行立即分配整个数组,然后让所有其他行指向足够的行:
a = malloc(rows * sizeof(float*));
a[0] = malloc(dim * rows * sizeof(float)); // Allocate the whole matrix on row #0
for (i = 1; i < rows; i++) {
a[i] = a[0] + i * dim; // sizeof(float) automatically taken into account as float* pointer arithmetics
}
...
m = malloc(rows * sizeof(float*));
m[0] = malloc(dim * rows * sizeof(float));
memcpy(m[0], a[0], dim * rows * sizeof(float));
(当然添加 NULL
检查)
我正在用 C 实现一个 K-means 算法。它在大多数情况下都运行良好,但是使用 Valgrind 调试它告诉我我正在做一个 "Invalid read of size 8 - Invalid write of size 8 - Invalid read of size 8" 使用 '''memcpy''' 开头。我认为问题不在那里,但我为多维浮点数组元素分配了一个值,该内存在某些时候使用带有 for 循环的“'malloc'”动态分配。因为 Valgrind 也告诉 "Address 0x572c380 is 0 bytes after a block of size 80 alloc'd".
我尝试将我分配的字节数加 1,因为我认为可能“'malloc'”"needed" 更多内存来完成它的工作,但没有任何改变.我知道这可能是一个基本错误,但我对这门语言还很陌生,在我的课程中它没有解释任何东西,所以 "technical"。我试图搜索错误的答案和解释,但我只发现了“'char'”数组的问题,而那些我理解的函数“'strcpy'”可以解决问题。浮点数组呢?这是第一次使用'''memcpy'''。
以下是引发这些 Valgrind 消息的代码片段。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
FILE* fp; //used to open a .txt file to read
char buf[100];
float ** a;
char * s;
int i;
int j;
int rows = 10;
fp = fopen("data.txt", "r");
if(fp==NULL){
perror("Error at open file.");
exit(1);
}
a = (float**) malloc(rows*sizeof(float*));
for(i=0; i<rows; i++){
s = fgets(buf, 100, fp); //reading .txt file
if (s==NULL){
break;
}
a[i] = malloc(dim*sizeof(float));
a[i][0] = atof(strtok(s, ","));
for(j=1; j<dim; j++){
a[i][j] = atof(strtok(NULL,",")); //save as float value the token read from a line in file, for example, from line "1.0,2.0,3.0" as first line -> get a[0][1] = 2.0
}
}
fclose(fp);
m = (float**) malloc(rows*sizeof(float*));
for (i=0; i<rows; i++){
m[i]=malloc(dim*sizeof(float)); //not initialized
}
memcpy(m, a, rows*dim*sizeof(float));
}
有人能帮我理解为什么它有效但 Valgrind 会引发这些错误消息吗?
您首先分配了一个 float*
数组, 然后 分配了多个 float
数组,因此您的最后一个 memcpy(m, a, rows*dim*sizeof(float))
复制了一个数组float*
(指向 float
的指针)指向另一个,但使用 rows * dim
浮点数,@SomeProgrammerDude 正确地指出了这一点。那会复制 pointers,而不是 values.
此外,正如@xing 所指出的,您正在分配 rows
但使用 righe
(您没有显示)。这可能是问题的原因。
我建议在第一行立即分配整个数组,然后让所有其他行指向足够的行:
a = malloc(rows * sizeof(float*));
a[0] = malloc(dim * rows * sizeof(float)); // Allocate the whole matrix on row #0
for (i = 1; i < rows; i++) {
a[i] = a[0] + i * dim; // sizeof(float) automatically taken into account as float* pointer arithmetics
}
...
m = malloc(rows * sizeof(float*));
m[0] = malloc(dim * rows * sizeof(float));
memcpy(m[0], a[0], dim * rows * sizeof(float));
(当然添加 NULL
检查)