Reputation: 12621
#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;
}
I need to set the values for the structure variables as 0xFF.
The above program is throwing an unhandled exception as "Unhandled exception at 0x61e1f5cf (msvcr90d.dll) in start.exe: 0xC0000005: Access violation writing location 0x00000000." please help me understand why it is.
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;
}
I tried like this bu still getting the exception.Please help.
Upvotes: 0
Views: 2373
Reputation: 183201
Since pstTask
is a global variable, this line:
psTask *pstTask;
is equivalent to this:
psTask *pstTask = 0x00000000;
and since you never later change it to point anywhere else (e.g., to properly allocated memory), this line:
memset(&(pstTask->stData), 0xFF, sizeof(pstTask->stData));
is equivalent to this:
memset(0x00000000, 0xFF, sizeof(pstTask->stData));
(since stData
is the first element of the psTask
structure, so has an offset of zero). This means that you're trying to write 0xFF
into memory location 0x00000000
(as well as the subsequent 47 bytes or so), rather than to memory that you actually have permission to write to (e.g. stack space, or space returned by malloc
).
Update for updated question:
This bit:
pstTask = (psTask*)malloc(sizeof(psTask));
pstTask = NULL;
allocates memory for a psTask
and points pstTask
at it — so far so good — but then it sets pstTask
right back to NULL
(i.e., not pointing anywhere valid). You need to remove that second line.
Also, after calling malloc
you should always examine its return value; if it returns NULL
, that means you're out of memory. So, you should write something like this:
pstTask = (psTask*)malloc(sizeof(psTask));
if(pstTask == NULL)
{
fprintf(stderr, "Out of memory.\n");
return 1;
}
printf("\npstTask->stData = %u\n",&pstTask->stData);
(In this specific case, I'm sure that malloc
will successfully return allocated memory, but you should really always check its return value.)
Upvotes: 7