PDA

View Full Version : random noise in record?



noeska
26-10-2008, 04:25 PM
OS: Windows XP
IDE: Delphi2005

On saving a packed record via an buffer to tfilestream i get some noise inside the record.

TMyRecord = packed record
name: string[255];
someint: int64;
end;
PMyRecord = ^TMyRecord;

system.New(myrecord);
//fillchar(filerecord.name, 255,0);
myrecord.name := 'name';

When i leave out the fillchar part i get some random chars inside the name part of the record. Why? It even seems ot include some names i used on the form?

I even have to use fillchar on the buffer i copy the record to.

Why cannot delphi inialize memory cleanly?

Thanks for your answers in advance.

chronozphere
26-10-2008, 04:35 PM
This is something that bothers me too sometimes. When you allocate dynamic or static memory, the initial contents of your variable will be random.

I can't really explain why the string contains component names. Probably because that memory is no longer in use. It's strange, because that data likely belonged to either delphi or your app, and both are still running.

One thing i wanted to say is that it's VERY important that you initialize any return value's in your functions, because they will return random data when you leave Result uninitialized. Those bugs can be very hard to kill. :twisted:

JernejL
26-10-2008, 04:47 PM
Why cannot delphi inialize memory cleanly?

That's not delphi's job, it's yours, memory manager's work is to allocate memory blocks asap, zerofilling them is unneccesary overhead in most cases, so it's your job to clear the memory that was allocated, ofcourse the memory allocated can sometimes contain garbage or parts of memory of whatever data that was allocated and deallocated there earlier. This is completely normal in other languages such as c / c++ as well.

noeska
26-10-2008, 05:14 PM
what is a neat way of cleaning a record then?

e.g. i now only have a fillchar(myrecord.name, 255,0); to do. But with a more complicated record i need many of these line and a fillchar on myrecord only is not valid.

Hmm the situation is even worse:

var
MyRecord : TMyRecord;
begin
MyRecord.name := 'Test';

When i pass this one on as @MyRecord to an buffer is contains garbage. Now how do i clean this one?

JSoftware
26-10-2008, 07:04 PM
Is it in the file where you save the record you get random chars? If so then it makes sense. Your record is probably created on the heap which will most likely be filled with random garbage before the instance gets created. The memory manager will not fill the allocated pointer with zeroes unless you use a specific method(AllocMem, I think)

There's probably no way around it. So just call FillChar(Myrecord, sizeof(myrecord), 0); first or initialize the variables

User137
26-10-2008, 09:55 PM
Why do you need to clear it in the first place? Isn't there an ending character or some first char indicating string lenght etc, don't know exactly how it works.

noeska
27-10-2008, 04:57 PM
if you do not save the complete record into a file you wont notice it. So you only need to clean them before usage if you want to save them in a file.

User137
27-10-2008, 08:00 PM
I know in memory there is noise, but how it actually effects the actual behavior of program did not come clear in this topic?

'text'+#0+'skdfjlkj' or '4textsdlkfj' would still show as 'text' would it not? I don't have time to test it at the moment but you missed my question.

noeska
28-10-2008, 05:15 PM
like i said it does not affect usage. But saving the record into a file and opening that file in an hex editor you see the random noise. I dont like that. so i clean the records before usage and get nice clean files with records.

Lowercase
29-10-2008, 08:20 AM
that depends types

for exemple string[255] is an array of 256 char, a string type always contains a 0 terminal, so if your string is 50 long, theres one 0 after, and 205 char of random memory. when you read your record in a file, you obtain the original string just because there's a trailing 0.

for an integer type, the size of an integer is fixed and know by advance, that's why you can write stream.write(i, sizeof(integer))

i don't know if i'm understable...

VilleK
29-10-2008, 08:34 AM
A string with predefined length (string[x]) is a "shortstring", the old string-type of Delphi 16-bit and Turbo Pascal, and it is not null-terminated. Instead the first byte is the string length. This means it can contain zero-characters. s:='te'#0'st' is a valid shortstring with length 5 (length stored in s[0]).

As already suggested just do a FillChar(MyRecord, sizeof(TMyRecord), 0) to clear the whole record at once.

Lowercase
29-10-2008, 11:57 AM
A string with predefined length (string[x]) is a "shortstring", the old string-type of Delphi 16-bit and Turbo Pascal, and it is not null-terminated. Instead the first byte is the string length. This means it can contain zero-characters. s:='te'#0'st' is a valid shortstring with length 5 (length stored in s[0]).

As already suggested just do a FillChar(MyRecord, sizeof(TMyRecord), 0) to clear the whole record at once.

Are you Sure ?

i made a record like noeska last week using delphi 6, i used an hex editor and i saw a null character just after the last char. will send some screen captures when i'm back home

AFAIK, Windows use "pchar type" natively ?

VilleK
29-10-2008, 01:12 PM
Delphi 2007:


type
TMyRecord = packed record
name: string[255];
someint: int64;
end;

procedure TForm2.FormCreate(Sender: TObject);
var
s : tmyrecord;
begin
fillchar(s,sizeof(tmyrecord),$80); //fill with non-zero for testing
s.name := '12'#0'34';
self.caption := inttostr(length(s.name)); //set breakpoint here
end;

The window caption will display the length of the string as 5. If you set a breakpoint where selected and press ctrl-f7 for evaluate and type "s,m" you will see a hex dump of the "s" variable. You will see that there is no zero after the string.

JernejL
29-10-2008, 04:50 PM
i made a record like noeska last week using delphi 6, i used an hex editor and i saw a null character just after the last char. will send some screen captures when i'm back home

So how exactly did you write the record to a file?

tpascal
29-10-2008, 05:46 PM
When you checks in delphi help the topic about functions and rutines by category you will note tha there are two sections, string and null terminated string rutines, the "string" rutines use the first character for denote the string lenght; nul terminate string are used as pchar.

Lowercase
29-10-2008, 07:24 PM
ok I found why... i used strpcopy function which result as pchar

TFileIndex = record
FileName: array[0..119] of char;
FilePos: integer;
FileLength: integer;
end;

//and later i use :


strpcopy(Dir.FileName, ExtractFileName(files.Strings[i]));





http://img259.imagevenue.com/loc534/th_07894_hexedit_122_534lo.JPG (http://img259.imagevenue.com/img.php?image=07894_hexedit_122_534lo.JPG)