1

Cの仕組みについてまた質問があります(VS2012でコンパイルされたANSI-C)

スタンドアロン プログラム (.exe) を .dll にリファクタリングしています。これは今のところ問題なく動作しますが、ロギングに関しては問題に遭遇します。説明させてください:

元のプログラムは、実行中にログ ファイルを書き込み、情報を画面に出力しました。私のdllはWebサーバー上で実行されるため、多くの人が同時にアクセスします

  • ログファイルを適切に処理する(そしてそれらをクリーンアップする)本当のチャンスはありません
  • コンソール ウィンドウが表示されない

したがって、私の目標は、ログ ファイルまたは画面に表示されるすべてのものを文字列のような変数 (C には文字列がないことを知っています) に書き込むことです。 dll ですが、C# で記述されています)。

Cではそのようなことは不可能であるため:

char z88rlog;
z88rlog="First log-entry\n";
z88rlog+="Second log-entry\n";

私には2つの可能性があります:

  1. char z88rlog[REALLY_HUGE];
  2. メモリの動的割り当て

私の考えでは、最初の方法は無視することです。

  • 潜在的なメモリの浪費はかなり大きい
  • よりも多くのメモリが必要な場合があるREALLY_HUGEため、バッファ オーバーフローが発生します。

それは私に2番目の方法を残します。私はそれについていくつかの作業を行い、2 つの解決策を考え出しましたが、どちらも適切に機能しません。

/* Solution 1 */    
void logpr(char* tmpstr)
{
    extern char *z88rlog;
    if (z88rlog==NULL)
    {
        z88rlog=malloc(strlen(tmpstr)+1);
        strcpy(z88rlog,tmpstr);
    }
    else
    {
        z88rlog=realloc(z88rlog,strlen(z88rlog)+strlen(tmpstr));
        z88rlog=strcat(z88rlog,tmpstr);
    }
}

ソリューション 1 (ソリューション 2 と同じ) では、新しいログ エントリを に渡しますchar tmpstr[255];。私の「ログファイル」z88rlogはグローバルに宣言されているためextern、アクセスする必要があります。次に、にメモリが割り当てられているかどうかを確認しz88rlogます。いいえの場合、ログ エントリのサイズ (+1 の場合\0) のメモリを割り当て、の内容を にコピーtmpstrz88rlogます。はいの場合、これまでのサイズ + (+1)z88rlogの長さでメモリを再割り当てします。tmpstr次に、 を使用して、2 つの「文字列」が結合されstrcatます。ダイレクト ウィンドウでブレークポイントを使用すると、次の出力が得られました。

z88rlog
0x00000000 <Schlechtes Ptr>
z88rlog
0x0059ef80 "start Z88R version 14OS"
z88rlog
0x0059ef80 "start Z88R version 14OS
opening file Z88.DYNÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍýýýý««««««««þîþîþîþ"

logpr の 3 回の連続した呼び出し ( strcpy/の前のブレークポイントstrcat) を示しています。最後に見分けがつかない意味不明な部分は、メモリ割り当てによるものです。その後、VS は、何らかの原因でデバッガーが にブレークポイントを設定したというエラー メッセージを出しますrealloc.c。これは明らかにうまくいかないので、私は素晴らしい解決策2を作成しました:

/* Solution 2 */
void logpr(char* tmpstr)
{
    extern char *z88rlog;
    char *z88rlogtmp;
    if (z88rlog==NULL)
    {
        z88rlog=malloc(strlen(tmpstr)+1);
        strcpy(z88rlog,tmpstr);
    }
    else
    {
        z88rlogtmp=malloc(strlen(z88rlog)+strlen(tmpstr+1));
        z88rlogtmp=strcat(z88rlog,tmpstr);
        free(z88rlog);
        z88rlog=malloc(strlen(z88rlogtmp)+1);
        memcpy(z88rlog,z88rlogtmp,strlen(z88rlogtmp)+1);
        free(z88rlogtmp);
    }
}

ここでの目的は、ログ ファイルのコピーを作成し、オリジナルのメモリを解放して、オリジナルの新しいメモリを新しいサイズで作成し、内容をコピーして戻すことです。また、一時コピーは malloc によって割り当てられるため、解放することを忘れないでください。これは に達するとすぐにクラッシュfreeし、ヒープが壊れている可能性があることを再度伝えます。

というわけで、とりあえず自由にコメントさせてください。これはうまく機能します-私の安堵のために-しかし、ログ文字列を作成しているときに、突然すべての文字z88rlogtmpがコピーされるわけではありません。しかし、すべてがまだ適切に機能しています。_heap_alloc (size_t size) in malloc.c size突然、ヒープが壊れている可能性があると再び言われるまで、デバッガーは、デバッガーによると、値が 1041の末尾にブレークポイントを設定します。

したがって、この「文字列の成長」を実現する方法は 2 つ (または 3 つ) ありますが、どれもうまくいきません。サイズを示すエラーが、配列が大きくなりすぎたという結論につながるのでしょうか? 私がやりたいことをよく説明して、誰かが私を助けてくれることを願っています:-) よろしくお願いします!

皮肉なことに、 Maybee に行って、コンピューター用の新しいヒープを購入する必要があります。RAMスロットに収まりますか?誰か良いブランドを推薦できますか?皮肉な

4

3 に答える 3

1

NULL解決策 1 では、終端文字にスペースを割り当てる必要があります。したがって、再割り当てにはもう 1 つのスペースを含める必要があります。

z88rlog=realloc(z88rlog,strlen(z88rlog)+strlen(tmpstr) + 1);

2 番目の解決策では、宛先文字列であるz88rlogtmp=strcat(z88rlog,tmpstr);ため、これについてはわかりません。z88rlog演奏mallocのみをご希望の場合は、

 z88rlogtmp=malloc(strlen(z88rlog)+1 // Allocate a temporary string
 strcpy(z88rlogtmp,z88rlog); // Make a copy
 free(z88rlog); // Free current string
 z88rlog=malloc(strlen(z88rlogtmp)+ strlen(tmpstr) + 1)); //Re-allocate memory
 strcpy(z88rlog, z88rlogtmp); // Copy first string
 strcat(z88rlog, tmpStr);  // Concatenate the next string
 free(z88rlogtmp); // Free the Temporary string
于 2013-04-03T11:42:43.633 に答える