我有一个小程序,它为通过命令行传递的参数生成一个SHA1摘要,并将它们存储在一个指向char数组的指针数组中(我认为):
#include <stdio.h>
#include <openssl/sha.h>
int entries = 0; // Keep track of entries added
int main(int argc, char **argv)
{
// Allocate space for the digest array
unsigned char **mds = malloc(1);
// Add entries to the digest, one for each argument passed
for(int k = 1; k < argc; k++) {
mds[k - 1] = malloc(SHA_DIGEST_LENGTH);
SHA1(argv[k], strlen(argv[k]), mds[k - 1]);
entries++;
}
// Print each 20-byte digest
for(int j = 0; j < entries; j++) {
for(int i = 0; i < SHA_DIGEST_LENGTH; i++) { printf("%02x ", *(mds[j] + i)); }
printf("\n");
}
}
最初我有unsigned char **mds = calloc(argc, SHA_DIGEST_LENGTH);
,每当我想添加另一个条目时,我就会尝试使用realloc()
(如果我不知道以后会有多少条目)。< / p>
但后来我发现我不需要这样做,我根本不需要分配任何空间?只是一个字节,它仍然可以正常工作。这对我来说似乎不对。
我是幸运的还是什么?我错过了什么?
答案 0 :(得分:2)
我只是幸运吗?
是
我错过了什么?
您的程序在分配的内存之外写入。这样做会导致未定义的行为。任何事情都可能发生,包括正确行为的出现。
添加一些free()
调用可能会导致一些crashers,但不能保证 - 毕竟未定义的行为是未定义的。
答案 1 :(得分:2)
你写的内存没有分配给你。幸运的是你到目前为止没有崩溃。
如果您的平台上有可用的valgrind,请尝试使用。它会告诉你有关这种变化的内存错误,以及何时分配忘记释放的内存。该程序运行速度较慢,但您只需将其用于测试目的。
答案 2 :(得分:1)
这部分:
// Allocate space for the digest array
unsigned char **mds = malloc(1);
分配大小为1
字节的内存块,并将其地址强制转换为unsigned char**
。然后在第一次迭代中,当你这样做时:
mds[k - 1] = malloc(SHA_DIGEST_LENGTH);
malloc
返回一个地址,该地址写入无效内存,导致未定义的行为。
您需要分配适当的内存块来保存指针,并且在每次迭代中,您将初始化每个指针以指向将包含 string 的内存块:
// allocate array of pointers:
unsigned char **mds = malloc( (argc - 1) * sizeof(unsigned char*) );
for (int k = 1; k < argc; k++) {
mds[k - 1] = malloc(SHA_DIGEST_LENGTH);
SHA1(argv[k], strlen(argv[k]), mds[k - 1]);
entries++;
}
...
// cleaning up:
for (int k = 1; k < argc; k++) {
free(mds[k - 1]);
}
free(mds);