Jump to page: 1 2 3
Thread overview
GC seems to crash my C-code function
Sep 16, 2021
frame
Sep 16, 2021
bauss
Sep 16, 2021
bauss
Sep 16, 2021
frame
Sep 16, 2021
bauss
Sep 16, 2021
frame
Sep 16, 2021
bauss
Sep 16, 2021
frame
Sep 17, 2021
frame
Sep 17, 2021
jfondren
Sep 17, 2021
frame
Sep 18, 2021
frame
Sep 18, 2021
frame
Sep 18, 2021
frame
Sep 18, 2021
frame
Sep 19, 2021
frame
September 16, 2021

I have C-code translated in D that acts sometimes incorrect if the GC has made some collect. I would like to know why.

  • Code runs correct if the GC collections are off
  • There are no allocations within the C-translated-code except throw new (but they are not called)
  • All allocations made in C-translated-code are still calloc/malloc `ed
  • Even if I disable the GC before calling the function and just enable it after there will be an incorrect result
  • Data passed to the function belongs to a struct and the function is called in a member function and is always correct

The main public function accepts a char* and returns a char*. Signature is like this:

char* fun(ref int, ref int, size_t, const char*, out int, out int, out int, uint);

Input paramter gets the pointer from char[] .ptr property (and length must be supplied too).

I didn't want to change the code much so I have some piece like that:

// const char *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
char* s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_".dup.ptr;

Could this cause the issue? But the pointer is not used outside the function where it's created.

September 16, 2021

On Thursday, 16 September 2021 at 10:28:37 UTC, frame wrote:

>

I have C-code translated in D that acts sometimes incorrect if the GC has made some collect. I would like to know why.

  • Code runs correct if the GC collections are off
  • There are no allocations within the C-translated-code except throw new (but they are not called)
  • All allocations made in C-translated-code are still calloc/malloc `ed
  • Even if I disable the GC before calling the function and just enable it after there will be an incorrect result
  • Data passed to the function belongs to a struct and the function is called in a member function and is always correct

The main public function accepts a char* and returns a char*. Signature is like this:

char* fun(ref int, ref int, size_t, const char*, out int, out int, out int, uint);

Input paramter gets the pointer from char[] .ptr property (and length must be supplied too).

I didn't want to change the code much so I have some piece like that:

// const char *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
char* s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_".dup.ptr;

Could this cause the issue? But the pointer is not used outside the function where it's created.

Use toStringz and not .ptr.

Or append \0 to your string.

September 16, 2021

On Thursday, 16 September 2021 at 10:48:19 UTC, bauss wrote:

>

On Thursday, 16 September 2021 at 10:28:37 UTC, frame wrote:

>

I have C-code translated in D that acts sometimes incorrect if the GC has made some collect. I would like to know why.

  • Code runs correct if the GC collections are off
  • There are no allocations within the C-translated-code except throw new (but they are not called)
  • All allocations made in C-translated-code are still calloc/malloc `ed
  • Even if I disable the GC before calling the function and just enable it after there will be an incorrect result
  • Data passed to the function belongs to a struct and the function is called in a member function and is always correct

The main public function accepts a char* and returns a char*. Signature is like this:

char* fun(ref int, ref int, size_t, const char*, out int, out int, out int, uint);

Input paramter gets the pointer from char[] .ptr property (and length must be supplied too).

I didn't want to change the code much so I have some piece like that:

// const char *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
char* s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_".dup.ptr;

Could this cause the issue? But the pointer is not used outside the function where it's created.

Use toStringz and not .ptr.

Or append \0 to your string.

Also see the documentation for "toStringz" which has this:

Important Note: When passing a char* to a C function, and the C function keeps it around for any reason, make sure that you keep a reference to it in your D code. Otherwise, it may become invalid during a garbage collection cycle and cause a nasty bug when the C code tries to use it.

It probably should tell that somewhere else too.

September 16, 2021

On Thursday, 16 September 2021 at 10:48:19 UTC, bauss wrote:

>

Use toStringz and not .ptr.

Or append \0 to your string.

Stupid me should really know that already, thanks =)
Of course I have dup'ed the \0 from the string away...

But still I don't know why it works if the GC is off?

September 16, 2021

On Thursday, 16 September 2021 at 11:06:04 UTC, frame wrote:

>

On Thursday, 16 September 2021 at 10:48:19 UTC, bauss wrote:

>

Use toStringz and not .ptr.

Or append \0 to your string.

Stupid me should really know that already, thanks =)
Of course I have dup'ed the \0 from the string away...

But still I don't know why it works if the GC is off?

Did you see my second response?

September 16, 2021

On Thursday, 16 September 2021 at 11:11:56 UTC, bauss wrote:

>

On Thursday, 16 September 2021 at 11:06:04 UTC, frame wrote:

>

On Thursday, 16 September 2021 at 10:48:19 UTC, bauss wrote:

>

Use toStringz and not .ptr.

Or append \0 to your string.

Stupid me should really know that already, thanks =)
Of course I have dup'ed the \0 from the string away...

But still I don't know why it works if the GC is off?

Did you see my second response?

Yes, but as I mentioned this pointer data isn't hold outside the function and the GC collect runs after data is processed, not in between. This pointer should be fully stack allocated and also newly generated each time the function is called, so I see no impact by the GC?

But GC collecting works now without issues.

September 16, 2021

On Thursday, 16 September 2021 at 11:35:27 UTC, frame wrote:

>

On Thursday, 16 September 2021 at 11:11:56 UTC, bauss wrote:

>

On Thursday, 16 September 2021 at 11:06:04 UTC, frame wrote:

>

On Thursday, 16 September 2021 at 10:48:19 UTC, bauss wrote:

>

Use toStringz and not .ptr.

Or append \0 to your string.

Stupid me should really know that already, thanks =)
Of course I have dup'ed the \0 from the string away...

But still I don't know why it works if the GC is off?

Did you see my second response?

Yes, but as I mentioned this pointer data isn't hold outside the function and the GC collect runs after data is processed, not in between. This pointer should be fully stack allocated and also newly generated each time the function is called, so I see no impact by the GC?

But GC collecting works now without issues.

My guess is something is undefined behavior in the C code, idk really

September 16, 2021

On 9/16/21 6:28 AM, frame wrote:

>

I have C-code translated in D that acts sometimes incorrect if the GC has made some collect. I would like to know why.

  • Code runs correct if the GC collections are off
  • There are no allocations within the C-translated-code except throw new (but they are not called)

...

>

I didn't want to change the code much so I have some piece like that:

// const char *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_";
char* s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_".dup.ptr;

Could this cause the issue? But the pointer is not used outside the function where it's created.

dup is a GC allocation. Are you using that in your C code? the GC might be collecting that string.

You are better off to cast away the immutable (as long as you are 100% sure the C code isn't writing to it), as the string literal will not be collected.

-Steve

September 16, 2021

On Thursday, 16 September 2021 at 15:34:25 UTC, Steven Schveighoffer wrote:

>

dup is a GC allocation. Are you using that in your C code? the GC might be collecting that string.

The compiler doesn't show that lines with -vgc. Maybe it knows that it is only stack allocated?

Technically, the GC could collect that data if it wants - it's not longer used after the function returns. At least I control that the GC cannot collect it till my data is processed, so there should be no problem.

I guess the C-methods did corrupt the memory which the compiler has reserved for that function data statically and then the GC collect marks it as free or some other UB.

>

You are better off to cast away the immutable (as long as you are 100% sure the C code isn't writing to it), as the string literal will not be collected.

-Steve

Yes, I changed it to stringz and a cast and the problem is gone so far. All char* are read only in the function or passed to stdlib functions that should not modify it.

September 16, 2021

On 9/16/21 1:08 PM, frame wrote:

>

On Thursday, 16 September 2021 at 15:34:25 UTC, Steven Schveighoffer wrote:

>

dup is a GC allocation. Are you using that in your C code? the GC might be collecting that string.

The compiler doesn't show that lines with -vgc. Maybe it knows that it is only stack allocated?

Technically, the GC could collect that data if it wants - it's not longer used after the function returns. At least I control that the GC cannot collect it till my data is processed, so there should be no problem.

Are you sure? Be very pedantic about what C functions do with the data you send it. Sometimes they store it somewhere to use later. Sometimes they expect it to be allocated by the C heap, etc.

Without seeing how you use it, I can't tell you if it's wrong or not.

>

I guess the C-methods did corrupt the memory which the compiler has reserved for that function data statically and then the GC collect marks it as free or some other UB.

>

You are better off to cast away the immutable (as long as you are 100% sure the C code isn't writing to it), as the string literal will not be collected.

Yes, I changed it to stringz and a cast and the problem is gone so far. All char* are read only in the function or passed to stdlib functions that should not modify it.

If it's a literal, you don't need to toStringz (which also allocates). All string literals are zero-terminated (and actually implicitly castable to immutable char *).

-Steve

« First   ‹ Prev
1 2 3