我正在C语言中实现K-means算法。大多数情况下,它运行良好,但是用Valgrind对其进行调试时告诉我,我正在执行“大小8的无效读取-大小8的无效写入-无效开头使用'''memcpy'''读取大小8“。我认为问题并不存在,但是我在其中为多维浮点数组元素分配了一个值,该内存在某个时候通过for循环通过'''malloc'''动态分配。 “因为Valgrind还告诉“地址0x572c380是在分配了大小为80的块之后为0字节”。
我试图在分配的字节数上加1,因为我认为也许'''malloc'''“需要”更多的内存来完成其工作,但是什么都没有改变。我知道这可能是一个基本错误,但是我对这门语言还是很陌生,在我的课程中,它并没有解释任何“技术性”的内容。我试图搜索错误的答案和解释,但是我只发现了'''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会提出这些错误消息吗?
答案 0 :(得分:0)
您首先要分配一个float*
数组,然后 分配几个float
数组,因此您的最后一个memcpy(m, a, rows*dim*sizeof(float))
复制了一个{{1} }(指向float*
的指针)到另一个,但使用float
浮点数,@ SomeProgrammerDude正确地指出了这一点。那会复制指针,而不是值。
此外,正如@xing指出的那样,您正在分配 rows * dim
,但使用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));
条支票)