www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can't understand if deallocation happens?

reply Suliman <evermind live.ru> writes:
import std.stdio;
import std.string;
import core.memory;

void main()
{
     char [] str = "aaa".dup;
     char [] *str_ptr = &str;

     writeln("before: ", str_ptr.ptr);// address of structure
     writeln(*str_ptr.ptr); // address of data
     str[] = "bbb"[]; // now writing to structure new data, so ptr 
would be point to them
     writeln("after: ", str_ptr.ptr);
     writeln("length: ", str_ptr.length);
     writeln("str_ptr point to: ", *str_ptr.ptr);

     writeln(str_ptr);
	
     writeln("before dealloc: ", str_ptr.length);
     GC.free(str_ptr.ptr);
     writeln(str_ptr);
     writeln("after dealloc: ", str_ptr.length);

}

As I understand str structure would have 2 data peace after 
writing "bbb" to it. But ptr will point to last one (to "bbb").

[aaa] [bbb]
--------+

So after appending "bbb" I should see that the size is 3, after 
appending 6. After GC again 3. But I see only 3 before and after 
GC:

 app.exe
before: 2641010 a after: 2641010 length: 3 str_ptr point to: b 19FE0C before dealloc: 3 19FE0C after dealloc: 3 And am I right understand that here memory should be GC-ed? Another question: writeln("before: ", str_ptr.ptr);// address of structure Is it's address from 0 of current App memory?
Jan 22 2017
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Sunday, 22 January 2017 at 12:49:11 UTC, Suliman wrote:
 import std.stdio;
 import std.string;
 import core.memory;

 void main()
 {
     char [] str = "aaa".dup;
     char [] *str_ptr = &str;

     writeln("before: ", str_ptr.ptr);// address of structure
     writeln(*str_ptr.ptr); // address of data
     str[] = "bbb"[]; // now writing to structure new data, so 
 ptr would be point to them
     writeln("after: ", str_ptr.ptr);
     writeln("length: ", str_ptr.length);
     writeln("str_ptr point to: ", *str_ptr.ptr);

     writeln(str_ptr);
 	
     writeln("before dealloc: ", str_ptr.length);
     GC.free(str_ptr.ptr);
     writeln(str_ptr);
     writeln("after dealloc: ", str_ptr.length);

 }

 As I understand str structure would have 2 data peace after 
 writing "bbb" to it. But ptr will point to last one (to "bbb").

 [aaa] [bbb]
 --------+

 So after appending
You do not append to anything, only overwrite it. There is no reallocation because "aaa".length == "bbb".length.
 "bbb" I should see that the size is 3, after appending 6. After 
 GC again 3. But I see only 3 before and after GC:

 app.exe
before: 2641010 a after: 2641010 length: 3 str_ptr point to: b 19FE0C before dealloc: 3 19FE0C after dealloc: 3 And am I right understand that here memory should be GC-ed? Another question: writeln("before: ", str_ptr.ptr);// address of structure Is it's address from 0 of current App memory?
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
 You do not append to anything, only overwrite it. There is no 
 reallocation because
 "aaa".length == "bbb".length.
I changed my code to: str_ptr.length +=1; str[] = "bbbb"[]; But now it's print length 4 before and after writing "bbb" to `str`. I expected that size will be 3+4=7.
Jan 22 2017
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 22 January 2017 at 13:34:10 UTC, Suliman wrote:
   str[] = "bbbb"[];
That means copy the contents of the right hand array into the location of the left hand array. It copies data, that operation will never change pointers. str = "bbbb"; would change the pointer.
Jan 22 2017
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 22 January 2017 at 12:49:11 UTC, Suliman wrote:
     writeln(str_ptr);
 	
     writeln("before dealloc: ", str_ptr.length);
     GC.free(str_ptr.ptr);
     writeln(str_ptr);
You freed the CONTENTS, but are printing the CONTAINER. str_ptr.ptr returns exactly the same thing as str.ptr or (*str_ptr).ptr, a pointer to the contents. When you write str_ptr, you print the pointer to the container. The container isn't moving, it is a stack variable and not managed by GC. If you want to see changes to the content pointer, just use it. string* in D is rarely what you want and I suggest you avoid using it until you have a strong grasp on the fundamentals of how arrays and pointers work. You're just confusing yourself by trying it right now.
 Is it's address from 0 of current App memory?
it is the virtual address space, the app doesn't necessarily use all the possible values.
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
 str_ptr.ptr returns exactly the same thing as str.ptr or 
 (*str_ptr).ptr, a pointer to the contents. When you write 
 str_ptr, you print the pointer to the container.
So str.ptr is just shortcut? Ok, but how to free memory from first located value (from `aaa`)? I changed my code to next: import std.stdio; import std.string; import core.memory; void main() { string str = "aaa".dup; string *str_ptr = &str; writeln("before: ", str_ptr.ptr);// address of structure writeln(*str_ptr.ptr); // address of data str = "bbbb"; // now writing to structure new data, so ptr would be point to them writeln("after: ", str_ptr.ptr); writeln("length: ", str_ptr.length); writeln("str_ptr point to: ", *str_ptr.ptr); writeln(str_ptr); writeln("before dealloc: ", str_ptr.length); //GC.free(str_ptr.ptr); // Error: function core.memory.GC.free (void* p) is not callable using argument types (immutable(char)*) writeln(str_ptr); writeln("after dealloc: ", str_ptr.length); } But I can't call `GC.free(str_ptr.ptr)` on string type, only on `char []`
Jan 22 2017
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 22 January 2017 at 14:04:55 UTC, Suliman wrote:
 So str.ptr is just shortcut?
str.ptr is the actual member. In D, pointers to structs (and an array is virtually the same as a struct) will automatically dereference themselves. T* t; t.member; // automatically rewritten into (*t).member) Your str_ptr variable in this code is completely useless and should be removed. It's presence only confuses you.
 Ok, but how to free memory from first located value (from 
 `aaa`)?
Supported answer: you don't, it has infinite lifetime and you're claiming it is immutable, but then trying to pull the memory out from under it! The supported solution is simply to let the garbage collector manage it. But..
     //GC.free(str_ptr.ptr); // Error: function 
 core.memory.GC.free (void* p) is not callable using argument 
 types (immutable(char)*)
If you must call the function though, you can simply `cast(void*) str.ptr`, or use `char[]` up above instead of `string` when declaring it, so it has a mutable pointer to begin with. Since you are using .dup anyway, both declarations are equally legal.
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
 Supported answer: you don't, it has infinite lifetime and 
 you're claiming it is immutable, but then trying to pull the 
 memory out from under it! The supported solution is simply to 
 let the garbage collector manage it.

 But..

     //GC.free(str_ptr.ptr); // Error: function 
 core.memory.GC.free (void* p) is not callable using argument 
 types (immutable(char)*)
If you must call the function though, you can simply `cast(void*) str.ptr`, or use `char[]` up above instead of `string` when declaring it, so it has a mutable pointer to begin with. Since you are using .dup anyway, both declarations are equally legal.
string str = "aaa"; writeln(str.length); // print 3 str = "bbbb"; writeln(str.length); //print 4 expected 3+4=7 [aaa][bbbb] (2 blocks) GC.free(cast(void*) str.ptr); writeln(str.length); //print 4
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
  	string str = "abc";
  	writeln(str.ptr);
  	str = "def";
  	writeln("last data: ", *(str.ptr));
  	writeln("old data: ", *(str.ptr-1)); // print nothing
  	writeln("old data: ", *(str.ptr-2)); // print c

It's look like that there is some gap between data, because `d` 
minus 1 should be `c`, but `c` I am getting only if I am doing 
`-2`. Why?
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
On Sunday, 22 January 2017 at 15:51:01 UTC, Suliman wrote:
  	string str = "abc";
  	writeln(str.ptr);
  	str = "def";
  	writeln("last data: ", *(str.ptr));
  	writeln("old data: ", *(str.ptr-1)); // print nothing
  	writeln("old data: ", *(str.ptr-2)); // print c

 It's look like that there is some gap between data, because `d` 
 minus 1 should be `c`, but `c` I am getting only if I am doing 
 `-2`. Why?
writeln("old data: ", cast(int)*(str.ptr-1)); #old data: 0 String is gaping by zero?? I thought they are continuously like abcdef ---↑ Where `↑` is equal to `ptr`.
Jan 22 2017
parent reply Mike Parker <aldacron gmail.com> writes:
On Sunday, 22 January 2017 at 15:59:47 UTC, Suliman wrote:
 On Sunday, 22 January 2017 at 15:51:01 UTC, Suliman wrote:
  	string str = "abc";
  	writeln(str.ptr);
  	str = "def";
  	writeln("last data: ", *(str.ptr));
  	writeln("old data: ", *(str.ptr-1)); // print nothing
  	writeln("old data: ", *(str.ptr-2)); // print c

 It's look like that there is some gap between data, because 
 `d` minus 1 should be `c`, but `c` I am getting only if I am 
 doing `-2`. Why?
writeln("old data: ", cast(int)*(str.ptr-1)); #old data: 0 String is gaping by zero?? I thought they are continuously like abcdef ---↑ Where `↑` is equal to `ptr`.
You have *two* distinct strings here. Why do you expect them to be sequential in memory? If you want them to be treated as one string, concatenate them. auto s1 = "abc"; auto s2 = "def"; auto s3 = s1 ~ s2;
Jan 22 2017
parent reply Suliman <evermind live.ru> writes:
 You have *two* distinct strings here.
Yes, I understand, I am trying to find out how it's work on low level. Any ideas why zero is used?
Jan 22 2017
parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Monday, 23 January 2017 at 06:42:00 UTC, Suliman wrote:
 You have *two* distinct strings here.
Yes, I understand, I am trying to find out how it's work on low level. Any ideas why zero is used?
string *literals* in d are nul terminated to ease interoperation with C so string s = "foo"; writefln("%d",cast(ubyte)s.ptr[3]); // use '.ptr' to skip bounds check prints 0u
Jan 22 2017