我意识到已经多次询问过,但没有一个解决方案能为我提供任何帮助。我正在编写一个实验室程序,在C中分配大量内存,特别是一个char指针数组,每个指针都在内存中分配了一个4096字节的页面大小。
char** pgs =(char**) malloc(sizeof(char *) * pages);
if(pgs == NULL){
printf("Failed to allocate memory");
exit(0);
}
int i;
for(i = 0; i < pages; i++){
pgs[i] = malloc(4096);
/*if(pgs[i] == NULL){
printf("Failed to allocate memory");
exit(0);
}*/
*pgs[i] = "\0";
/*if(pgs[i] == NULL){
printf("Failed to allocate memory");
exit(0);
}*/
}
在程序的中间,随机访问和修改此数组的元素,以便引发颠簸(作为实验室的一部分):
while(time(NULL) - startTime < seconds){
long rando = rand() % pages;
if(modify > 0){
*pgs[rando]++;
}
else{
long temp = *pgs[rando];
}
在程序结束时,我试图释放这段记忆:
for(i = 0; i < pages; i++){
free(pgs[i]);
}
free(pgs);
然而,我得到了恐惧&#34;无效指针&#34;错误。如果有人对如何解决这个问题有任何建议或了解,请分享。
答案 0 :(得分:2)
您展示的程序片段会出现许多问题,其中一些问题已在评论中确定:
但是,主要问题是问题中的代码使用*pgs[rando]++
,用于修改已分配的内存。这相当于*(pgs[rando]++)
,它增加指针然后读取值并丢弃它 - 而不是等同于(*pgs[rando])++
,它将修改字节pgs[rando][0]
。问题中的代码应该生成关于value computed is not used
的警告(如果确保编译并将所有警告视为错误,则会出现错误)。因为你的代码正在递增指针,所以返回到带有free()
的内存分配系统的值通常与内存分配系统返回给你的值不同,所以你确实传递了无效的指针到free()
。
此代码避免了上述问题。它执行固定次数的迭代并且不使用time()
。它打印sum
,以便优化器无法优化对内存的读访问。
/* SO 4971-2352 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { PAGESIZE = 4096 };
int main(void)
{
int pages = PAGESIZE;
char **pgs = (char **)malloc(sizeof(char *) * pages);
if (pgs == NULL)
{
fprintf(stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < pages; i++)
{
pgs[i] = malloc(PAGESIZE);
if (pgs[i] == NULL)
{
fprintf(stderr, "Failed to allocate memory\n");
exit(EXIT_FAILURE);
}
memset(pgs[i], '\0', PAGESIZE); // Or use calloc()!
}
size_t sum = 0;
for (int i = 0; i < PAGESIZE * PAGESIZE; i++)
{
int pagenum = rand() % pages;
int offset = rand() % PAGESIZE;
int modify = i & 2;
if (modify != 0)
{
pgs[pagenum][offset]++;
}
else
{
sum += pgs[pagenum][offset];
}
}
printf("Sum: 0x%.8zX\n", sum);
for (int i = 0; i < pages; i++)
free(pgs[i]);
free(pgs);
return 0;
}
我调用了代码thrash31.c
并使用以下代码将其编译为thrash31
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror thrash31.c -o thrash31
$
当使用计时程序运行时,我得到了输出:
$ timecmd -u -- thrash31
2018-04-07 15:48:58.546809 [PID 9178] thrash31
Sum: 0x001FE976
2018-04-07 15:48:59.355508 [PID 9178; status 0x0000] - 0.808699s
$
因此,运行大约需要0.8秒。它每次生成的总和是相同的,因为代码不会为随机数生成器播种。