2

I need to compute a signature (a kind of a hash) for my object. The computation requires many per-character operations, so to speed this procedure up, my code operates on CString, and after that converts computed CString to final NSString. The stub code looks like this:

- (NSString *)signature
{
    NSString *signatureString = @"?";
    char *buffer;

    buffer = malloc(sizeof(char)*(self.hashLength+1));
    if ( buffer ) {
        // Code computing a signature into the buffer

        signatureString = [NSString stringWithCString:buffer
                                             encoding:NSASCIIStringEncoding];
        free(buffer);
    }

    return signatureString;
}

I expected that upon creation of NSString characters from source CString are copied into internal structure of NSString object. However in runtime I am getting the error:

malloc: *** error for object 0x8f734d4: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug

This looks like chars are not copied, but used from their original memory location. Is it really so? Does it mean that I need to not free allocated memory? Will the NSString deallocate that CString memory upon object destruction?

I can not find any documentation explaining that issue, but because I want to avoid memory leak obviously, I would prefer to be sure,

Voyteck
  • 354
  • 2
  • 13
  • What that error message usually means is that you've written beyond the bounds of the space you allocated. Probably self.hashLength isn't return sufficient space for the checksum, or the code to create the signature is blowing the boundaries. Try taking the NSString creation out and see if it still crashes. – David Berry Mar 05 '14 at 23:37
  • 1
    `stringWithCString:encoding:` most definitely does not need the buffer once it's done. In addition to overwriting the buffer, as David suggests, it could also be that you don't have a terminating NULL in your C string. In that case the stringWithCString method would go beyond the bounds of your buffer. – Duncan C Mar 06 '14 at 01:32
  • Terminating nul was placed at the end - but thanks. :-) @David: yes it was a bug in signature computation code. I did the opposite to your suggestion actually - I commented out signature computation leaving NSString creation there, and the error disappeared. This motivated me enough to trace the code and find the bug. Thanks :-) for a hint. – Voyteck Mar 06 '14 at 08:37

2 Answers2

1

So the answer is:

Yes, [NSString stringWithCString:encoding:] does copy the source CString to it's internal structure. If the source CString was allocated on a memory heap, it can be freed immediately after NSString object creation.

The error message I got, was caused be a bug inside signature computing code. Due to a wrongly initialized index variable in a for loop, code was writing beyond the allocated memory.

Voyteck
  • 354
  • 2
  • 13
0

Use a different encoding.

NSASCIIStringEncoding DOcs state:

Strict 7-bit ASCII encoding within 8-bit chars; ASCII values 0…127 only.

NSMacOSRomanStringEncoding is a good choice because it handles all 8-bit values.

zaph
  • 111,848
  • 21
  • 189
  • 228
  • Thanks for a hint Zaph, but this is not a problem here. The signature consists of basic ASCII characters only (letters and punctuations), so 0..127 coded on 8 bits fits. But I tested your suggestion anyway - no difference. – Voyteck Mar 06 '14 at 08:09