0

コマンドライン経由で渡された引数の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()いました(後でエントリの数がわからない場合)。

しかし、それを行う必要がなく、スペースをまったく割り当てる必要さえないことがわかりましたか? ほんの 1 バイトで、それでも問題なく動作します。それは私には正しくないようです。

私は運が良かっただけですか?私は何が欠けていますか?

4

3 に答える 3

2

自分に割り当てられていないメモリに書き込んでいます。今のところクラッシュがないのは幸運です。

プラットフォームで使用可能な場合は、valgrind を使用してみてください。このような種類のメモリ エラーと、解放するのを忘れたメモリを割り当てたときの両方について通知されます。プログラムの実行は遅くなりますが、テスト目的でのみ実行する必要があります。

于 2013-10-09T23:23:49.487 に答える
2

私は運が良かっただけですか?

はい。

私は何が欠けていますか?

プログラムは、割り当てられたメモリの外に書き込みます。これを行うと、未定義の動作が発生します。正しい動作のように見えることを含め、あらゆることが起こる可能性があります。

free()いくつかの呼び出しを追加すると、おそらくいくつかのクラッシャーが発生しますが、保証はありません-未定義の動作は未定義です.

于 2013-10-09T23:18:33.207 に答える
1

この部分:

// Allocate space for the digest array
unsigned char **mds = malloc(1);

サイズ1byte のメモリ ブロックを割り当て、そのアドレスを にキャストします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);
于 2013-10-09T23:22:05.587 に答える