2012-01-05 14 views
0

は私が0xFFのように構造体変数の値を設定する必要があります "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; 
} 

が含まれます。未処理の例外START.EXE中(msvcr90d.dll):0xc0000005で:アクセス違反の書き込み場所0x00000000の

上記プログラムは、「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 

EDITED:

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; 
} 

私はまだexception.Pleaseの助けを得て、このBUのように試してみました。 pstTask以来

答えて

7

はグローバル変数であり、このライン:

psTask *pstTask; 

がこれに相当します

psTask *pstTask = 0x00000000; 

と後で適切に割り当てられたために、例えば(どこにも指すように変更したことがないので、メモリ)、この行:

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

はこれに相当します。

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

stDatapsTask構造の最初の要素であるので、ゼロオフセットしているため)。これは、実際に書き込み権限があるメモリ(例えば、スタック領域、またはmallocによって返された領域)ではなく、(以降の47バイトほど)と同様に、に書き込むことを意味します。


更新更新の質問には:

このビット:

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

が—とても良い今のところそれでpsTaskとポイントpstTask —にメモリを割り当てますが、それはpstTask権を設定し、 NULLに戻ります(つまり、有効な場所を指していない)。その2行目を削除する必要があります。

また、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が正常に割り当てられたメモリを返すことを確信しているが、あなたは本当には常にその戻り値をチェックする必要があります。)

+0

+1。いい答え。 –

+0

@ruakh:私をはっきりと説明してくれてありがとう。私はいくつかの変更を行ったが、まだ私は例外の男を得ている。 – Angus

+0

第1の等価は、一般的に真である。なぜなら、「0x00000000」はヌルポインタ定数であるからである。 'pstTask'にはヌルポインタ値が格納されていますが、必ずしもすべてのビットがゼロではありません(ただし、Windows上にありますが、プログラムが実行されている環境です)。私はそれが '0x00000000'ではなくヌルポインタの点で考えることを明確にしています。 –

関連する問題