start.exe中0x61e1f5cf(msvcr90d.dll)的未处理异常:0xC0000005:访问冲突写入位置0x00000000

时间:2012-01-05 01:44:39

标签: c

包括“stdafx.h”

#include<stdio.h>
#include<string.h>
#define MAX_ET_TABLES 10

typedef struct{
    unsigned char  ucVersion;
    unsigned char enMonitor;
    unsigned short uPid;
}SData_t;
typedef struct{
    unsigned char ucVersion;
    unsigned short uID;
    unsigned int uiCollected;
    SData_t st[MAX_ET_TABLES];
}STData_t; 

typedef struct{
   STData_t stData;   
}psTask;

psTask *pstTask;

int main()
{
    printf("\npstTask->stData = %u\n",&pstTask->stData);
    memset(&(pstTask->stData), 0xFF, sizeof(pstTask->stData)); 
    return 0;
}

我需要将结构变量的值设置为0xFF。

上面的程序将一个未处理的异常抛出为“未处理的异常” start.exe中的0x61e1f5cf(msvcr90d.dll):0xC0000005:访问冲突写入位置 0x00000000。“请帮我理解原因。

      page    ,132
        title   memset - set sections of memory all to one byte
;***
;memset.asm - set a section of memory to all one byte
;
;       Copyright (c) Microsoft Corporation. All rights reserved.
;
;Purpose:
;       contains the memset() routine
;
;*******************************************************************************

        .xlist
        include cruntime.inc
        .list

page
;***
;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value"
;
;Purpose:
;       Sets the first "count" bytes of the memory starting
;       at "dst" to the character value "value".
;
;       Algorithm:
;       char *
;       memset (dst, value, count)
;               char *dst;
;               char value;
;               unsigned int count;
;               {
;               char *start = dst;
;
;               while (count--)
;                       *dst++ = value;
;               return(start);
;               }
;
;Entry:
;       char *dst - pointer to memory to fill with value
;       char value - value to put in dst bytes
;       int count - number of bytes of dst to fill
;
;Exit:
;       returns dst, with filled bytes
;
;Uses:
;
;Exceptions:
;
;*******************************************************************************

        CODESEG

    extrn   _VEC_memzero:near
    extrn   __sse2_available:dword

        public  memset
memset proc \
        dst:ptr byte, \
        value:byte, \
        count:dword

        OPTION PROLOGUE:NONE, EPILOGUE:NONE

        .FPO    ( 0, 3, 0, 0, 0, 0 )

        mov     edx,[esp + 0ch] ; edx = "count"
        mov     ecx,[esp + 4]   ; ecx points to "dst"

        test    edx,edx         ; 0?
        jz      short toend     ; if so, nothing to do

        xor     eax,eax
        mov     al,[esp + 8]    ; the byte "value" to be stored

; Special case large block zeroing using SSE2 support
    test    al,al ; memset using zero initializer?
    jne     dword_align
    cmp     edx,0100h ; block size exceeds size threshold?
    jb      dword_align
    cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?
    je      dword_align

    jmp     _VEC_memzero ; use fast zero SSE2 implementation
    ; no return

; Align address on dword boundary
dword_align:

        push    edi             ; preserve edi
        mov     edi,ecx         ; edi = dest pointer

        cmp     edx,4           ; if it's less then 4 bytes
        jb      tail            ; tail needs edi and edx to be initialized

        neg     ecx
        and     ecx,3           ; ecx = # bytes before dword boundary
        jz      short dwords    ; jump if address already aligned

        sub     edx,ecx         ; edx = adjusted count (for later)
adjust_loop:
        mov     [edi],al
        add     edi,1
        sub     ecx,1
        jnz     adjust_loop

dwords:
; set all 4 bytes of eax to [value]
        mov     ecx,eax         ; ecx=0/0/0/value
        shl     eax,8           ; eax=0/0/value/0

        add     eax,ecx         ; eax=0/0val/val

        mov     ecx,eax         ; ecx=0/0/val/val

        shl     eax,10h         ; eax=val/val/0/0

        add     eax,ecx         ; eax = all 4 bytes = [value]

; Set dword-sized blocks
        mov     ecx,edx         ; move original count to ecx
        and     edx,3           ; prepare in edx byte count (for tail loop)
        shr     ecx,2           ; adjust ecx to be dword count
        jz      tail            ; jump if it was less then 4 bytes

>         rep     stosd         // the arrow comes here when that exception is thrown

main_loop_tail:
        test    edx,edx         ; if there is no tail bytes,
        jz      finish          ; we finish, and it's time to leave
; Set remaining bytes

tail:
        mov     [edi],al        ; set remaining bytes
        add     edi,1

        sub     edx,1           ; if there is some more bytes
        jnz     tail            ; continue to fill them

; Done
finish:
        mov     eax,[esp + 8]   ; return dest pointer
        pop     edi             ; restore edi

        ret

toend:
        mov     eax,[esp + 4]   ; return dest pointer

        ret

memset  endp

        end
  

编辑:

int main()
{
    psTask *pstTask;
    pstTask = (psTask*)malloc(sizeof(psTask));
    pstTask = NULL;
    printf("\npstTask->stData = %u\n",&pstTask->stData);
    memset(&(pstTask->stData), 0xFF, sizeof(pstTask->stData)); 
    return 0;
}

我试过这样的事情仍然得到例外。请帮助。

1 个答案:

答案 0 :(得分:7)

由于pstTask是一个全局变量,因此该行:

psTask *pstTask;

相当于:

psTask *pstTask = 0x00000000;

并且由于您以后从未将其更改为指向其他任何位置(例如,正确分配内存),此行:

    memset(&(pstTask->stData), 0xFF, sizeof(pstTask->stData));

相当于:

    memset(0x00000000, 0xFF, sizeof(pstTask->stData));

(因为stDatapsTask结构的第一个元素,所以偏移量为零)。这意味着您正在尝试将0xFF写入内存位置0x00000000(以及后续的47个字节左右),而不是写入您实际有权写入的内存(例如堆栈空间) ,或malloc)返回的空格。


更新以获取更新的问题:

这一位:

    pstTask = (psTask*)malloc(sizeof(psTask));
    pstTask = NULL;

psTask分配内存并为其指出pstTask - 到目前为止一直很好 - 但随后将pstTask设置回NULL(即,不指向任何地方)有效)。你需要删除第二行。

此外,在调用malloc之后,您应该始终检查其返回值;如果它返回NULL,那意味着你的内存不足。所以,你应该写这样的东西:

    pstTask = (psTask*)malloc(sizeof(psTask));
    if(pstTask == NULL)
    {
        fprintf(stderr, "Out of memory.\n");
        return 1;
    }
    printf("\npstTask->stData = %u\n",&pstTask->stData);

(在这种特定情况下,我确信malloc将成功返回已分配的内存,但您应该始终检查其返回值。)