我有一个用C语言编写缓存模拟的项目,到目前为止我一直在为数组和程序崩溃分配空间。请帮帮我。 我必须在这个程序中使用指针。当我在主函数中创建数组时,没有任何问题,但是在指向全局之后,程序开始崩溃,我必须将它全局化。它的要求之一。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
int INDEXLENGTH; // global variable for num of bits in index
int OFFSETLENGTH; // global variable for num of bits in byte offset
int TAGBITS; // global variable for num of bits in the tag
int misses=0; //variable for total number of misses
int hits=0;
int **tagAr; // LRUArray pointer
int **lruAr; // tagArray pointer
int cacheSize; // user specified size of cache
int blockSize; // user specified size of each block
int linesperset;
int sets;
int main(void)
{
int i; // simply a few variables for future for loops
int j;
printf("Welcome to Lab A Cache Simulator by Divya, Alex and Jenn.\n");
printf("To begin, please input the size of the cache you will be simulating in bytes.\n");
scanf(" %d", &cacheSize); // (cache size in bytes) is read in from the user
printf("You have inputed this: %d\n", cacheSize);
printf("Next, please input the size of each cache line in bytes.\n");
scanf(" %d", &blockSize); // blocksize is read in from the user
printf("You have inputed this: %d\n", blockSize);
printf("Finally, please input the number of ways of associativity for this cache.\n");
printf("Also, input the number as a power of 2.\n");
scanf(" %d", &linesperset); // linesperset is read in from the user
printf("You have inputed this: %d\n", linesperset);
sets = (cacheSize/(blockSize*linesperset));
printf("Variable sets is: %d\n", sets);
tagAr=(int **)malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) tagAr[i]=(int *)malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
lruAr=(int **)malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) lruAr[i]=(int *)malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
for (i=0; i<sets; i++)
{
for (j=0; j<blockSize; j++)
{
tagAr[i][j] = -1;
lruAr[i][j] = -1;
}
}
for (i = 0; i < sets; i++) //This part of the code prints array for debuging purposes
{
for (j = 0; j < blockSize; j++)
{
printf(" %d", lruAr[i][j]);
}
printf("\n");
printf("\n");
}
printf("This is the value of IndexLength before setting, should be 0 : %d\n", INDEXLENGTH); //only for debuging purposes
setIndexLength();
printf("This is the value of IndexLength after setting: %d\n", INDEXLENGTH); //only for debuging purposes
printf("This is the value of OffsetLength before setting, should be 0 : %d\n", OFFSETLENGTH); //only for debuging purposes
offsetLength();
printf("This is the value of OffsetLength after setting: %d\n", OFFSETLENGTH); //only for debuging purposes
return misses;
}
答案 0 :(得分:4)
您有一个拼写错误,在下面的代码中,您设置了tagAr[i]
两次并且从未设置lruAr[i]
;
tagAr=(int **)malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) tagAr[i]=(int *)malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
lruAr=(int **)malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) tagAr[i]=(int *)malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
第二次tagAr[i]
作业应该是lruAr[i]
。
所以,这就是你想要的:
tagAr=malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) tagAr[i]=malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
lruAr=malloc(sets*sizeof(int *)); // allocating space for "l" array pointers
for (i=0; i<sets; i++) lruAr[i]=malloc(linesperset*sizeof(int)); //allocates space for k columns for each p[i]
答案 1 :(得分:3)
这不是一个真正的答案,而是Pankrates非常好的建议的后续行动。
如果您在valgrind
下运行程序(在使用调试信息进行编译并且没有优化之后,为了安全起见)
$ gcc -O0 -g -o test.o -W -Wall test.c # Compile
$ valgrind ./test.o # run simple Valgrind
你得到:
==26726== Use of uninitialised value of size 8
==26726== at 0x4008C5: main (test.c:54)
==26726==
==26726== Invalid write of size 4
==26726== at 0x4008C5: main (test.c:54)
==26726== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==26726==
==26726==
告诉您在源文件的第54行,您正在写入未初始化的变量。你没有分配的东西。 Valgrind告诉你什么和在哪里。要发现为什么,该行是:
lruAr[i][j] = -1;
所以你检查你分配的地方lruAr
(valgrind说它没有被分配!),你很快就会发现看起来像是一个复制粘贴错误:
for(i = 0; i)malloc(linespersetsizeof(int)); //为每个p [i]
分配k列的空间tagAr=(int **)malloc(sets*sizeof(int *));
for (i=0; i<sets; i++) {
tagAr[i]=(int *)malloc(linesperset*sizeof(int)); // <-- ORIGINAL LINE
}
lruAr=(int **)malloc(sets*sizeof(int *));
for (i=0; i<sets; i++) {
tagAr[i]=(int *)malloc(linesperset*sizeof(int)); // <-- THE COPY ("tagAr"?)
}
解决方案是Charlie Burns所描述的。
Valgrind可以帮助您做更多的事情,并且可以帮助您拦截更多更微妙的错误 - 不会让您的应用程序崩溃的错误 和可重现
出于同样的原因,不使用强制转换(或仅作为最后手段使用)。通过强制转换,您告诉编译器“我知道更好”。事实上,编译器通常比你和我以及大多数其他人都知道得更好。通过不使用演员表,只要你不知不觉地做了一些可疑的事情就让它站起来说话,而不是愚蠢地继续做你告诉它做的事情而不是你的意思它要做。
(很抱歉,长时间和光顾的咆哮。但我被咬了很多次,我想也许我可能会省你一些皮肤:-))
“仍然崩溃”。好的,我们在更新源代码后再次运行valgrind
,这次我们得到了
==28686== Invalid write of size 4
==28686== at 0x4008B8: main (test.c:54)
==28686== Address 0x51e00a0 is 0 bytes after a block of size 16 alloc'd
==28686== at 0x4C2C27B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==28686== by 0x4007F3: main (test.c:43)
==28686==
==28686== Invalid write of size 4
==28686== at 0x4008E2: main (test.c:55)
==28686== Address 0x51e0190 is 0 bytes after a block of size 16 alloc'd
==28686== at 0x4C2C27B: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==28686== by 0x400852: main (test.c:46)
注意:我们在块之后写 0个字节。这意味着我们有缓冲区溢出:我们 分配了一个数组,但它太小。或者我们的写作太大了。
阵列分配在第43和46行(两个循环的mallocs)并写在这里:
tagAr[i][j] = -1;
lruAr[i][j] = -1;
...所以这意味着tagAr[i]
有宽度,但blockSize
更大。
这可能是由于我插入了荒谬的数据,所以你必须自己检查一下。但很明显,您分配了linesperset
个元素,并编写了blockSize
个元素。至少,blockSize
绝不允许超过linesperset
。
以下代码通过了valgrind
次测试。我还添加了一个检查内存确实已经分配:它几乎总是不必要的,如果没有它,程序将几乎从不崩溃和coredump。如果几乎从不且不应该对你不够好,你最好检查一下。
// allocating space for "l" array pointers
tagAr=malloc(sets*sizeof(int *));
lruAr=malloc(sets*sizeof(int *));
if ((NULL == tagAr)||(NULL == lruAr)) {
fprintf(stderr, "out of memory\n");
}
for (i=0; i < sets; i++) {
tagAr[i] = malloc(linesperset*sizeof(int));
lruAr[i] = malloc(linesperset*sizeof(int));
for (j=0; j < linesperset; j++) {
tagAr[i][j] =
lruAr[i][j] = -1;
}
}
出于同样的原因,即使很多人称它为偏执和肛门保持,现代垃圾收集语言嘲笑它,一旦你完成就释放每个分配的指针是一个好习惯,并将其设置为NULL好的措施(不是为了防止游荡 - 而是为了确保你没有在某个地方使用过时的价值)。
// To free:
for (i=sets; i > 0; ) {
i--;
// To be really sure, you might want to bzero()
// lruAr[i] and tagAr[i], or better still, memset()
// them to an invalid and easily recognizable value.
// I usually use 0xDEADBEEF, 0xDEAD or 0xA9.
free(lruAr[i]); lruAr[i] = NULL;
free(tagAr[i]); tagAr[i] = NULL;
}
free(lruAr); lruAr = NULL;
free(tagAr); tagAr = NULL;
(上述做法,包括来自Writing Solid Code的0xA9值)。