-1

バイト配列へのポインターを含む構造体があります。

ポインターを設定するには、次の 2 つの方法を試しました。

1 malloc を使用してから memcpy バイト配列データを使用します (以下のコードではコメントアウトされています)。

2 単純にポインタをコピーします。

#include "stdlib.h"
#include "string.h"
#include "stdio.h"

typedef struct _element
{
    unsigned char *pValue;
    int nLength;
} Element;

Element* ElementCreate(void)
{
    Element *pElement = (Element*)malloc(sizeof(*pElement));

    pElement->pValue = NULL;
    pElement->nLength = 0;

    return pElement;
}

void ElementDestroy(Element **ppElement)
{
    Element *pElement = NULL;

    if (!ppElement)
        return;

    pElement = *ppElement;

    //free(pElement->pValue);
    //pElement->pValue = NULL;

    free(pElement);
    *ppElement = NULL;
}

void ElementSetValue(Element *pElement, unsigned char *pValue, int nLength)
{
    //pElement->pValue = (unsigned char*)malloc(nLength * sizeof(*(pElement->pValue)));
    //if (!(pElement->pValue))
    //    return;

    //memcpy(pElement->pValue, pValue, nLength);

    pElement->pValue = pValue;
    pElement->nLength = nLength;
}

void ElementWriteValue(const Element *pElement)
{
    int nIndex = 0;
    for (; nIndex < pElement->nLength; nIndex++)
        printf("%02X ", pElement->pValue[nIndex]);
}

int main(void)
{
    //unsigned char myValue[] = { 0x01, 0x02, 0x03 };
    //int nLength = sizeof(myValue) / sizeof(myValue[0]);

    Element *pElement = ElementCreate();

    {
        unsigned char myValue[] = { 0x01, 0x02, 0x03 };
        int nLength = sizeof(myValue) / sizeof(myValue[0]);

        ElementSetValue(pElement, myValue, nLength);
    }

    // How come this writes out correct value?
    ElementWriteValue(pElement);

    ElementDestroy(&pElement);

    return 0;
}

(簡潔にするためにエラーチェックは省略されています)

どの方法が正しいですか?

「}」の後に myValue が破棄されるため、2 は失敗すると予想されます。

printf("%02X ", pElement->pValue[nIndex]);

ゴミデータを書き出すでしょうが、うまくいくようです。なんで?

4

2 に答える 2

1

これは未定義の動作であり、そのサブセットが「正しく機能する」ことになっています。

配列myValueは次の範囲外}です。この時点で、myValue格納されたメモリの場所は再利用できますが、変更されないままではない可能性があるため、コードは機能しているように見えます。

正しいアプローチはmalloc()memcpy()およびfree()です。

于 2012-09-26T11:07:10.757 に答える
0

私たちが入るとき

{
    unsigned char myValue[] = { 0x01, 0x02, 0x03 };
    int nLength = sizeof(myValue) / sizeof(myValue[0]);

    ElementSetValue(pElement, myValue, nLength);
}

つまり、myValue 用にメモリが予約されます。そして、それを ( の後}) 残すと、myValue に関連するメモリはもう予約されておらず、解放されていますが、内容は変更されていません。そのため、メモリにアクセスでき、その内容は変更されません。アプリケーションがマルチスレッド アプリケーションの場合、myValue メモリに関連するデータが別のスレッドによって変更される大きなリスクがあります。この場合、常に同じメモリ空間にアクセスできますが、メモリの内容が変化することがわかります。

于 2012-09-26T11:11:40.890 に答える