I have just updated to Lion and now my app is crashing which was working fine in older version. It crash on memset function with no logs.
unsigned char *theValue;
add(theValue, someotherValues);
I have passed theValue reference to function
add(unsigned char *inValue, some other perameter) {
memset(inValue,0,sizeOf(inValue)); // **here it is crashing**
}
Is there really no code between the declaration of theValue and the call to add()? If so, then that's your problem. You are passing a random value as the first parameter to memset().
For this code to make sense, you have to allocate a block of memory for theValue and pass its size to add(), like so:
unsigned char *theValue = new unsigned char[BUFSIZE]; // Or malloc
add(theValue, BUFSIZE, ...);
void add(unsigned char *inValue, size_t bufsize, ...) {
memset(inValue, 0, bufsize);
...
}
Do you allocate memory for inValue?
1)
add(unsigned char *inValue, some other perameter) {
inValue = (unsigned char*)malloc(sizeof(inValue));
memset(inValue,0,sizeOf(inValue)); // **here it is crashing**
}
2)
theValue = (unsigned char*)malloc(sizeof(inValue));
add(theValue, ...)
unsigned char *theValue;
This points to a random bit of memory (or 0). Until you call malloc you don't own what it's pointing at so you can't really memset it.
Related
I had to deal with a really old codebase in my company which had C++ apis exposed via perl.
In on of the code reviews, I suggested it was necessary to garbage collect memory which was being allocated in c++.
Here is the skeleton of the code:
char* convert_to_utf8(char *src, int length) {
.
.
.
length = get_utf8_length(src);
char *dest = new char[length];
.
.
// No delete
return dest;
}
Perl xs definition:
PROTOTYPE: ENABLE
char * _xs_convert_to_utf8(src, length)
char *src
int length
CODE:
RETVAL = convert_to_utf8(src, length)
OUTPUT:
RETVAL
so, I had a comment that the memory created in the c++ function will not garbage collected by Perl. And 2 java developers think it will crash since perl will garbage collect the memory allocated by c++. I suggested the following code.
CLEANUP:
delete[] RETVAL
Am I wrong here?
I also ran this code and showed them the increasing memory utilization, with and without the CLEANUP section. But, they are asking for exact documentation which proves it and I couldn't find it.
Perl Client:
use ExtUtils::testlib;
use test;
for (my $i=0; $i<100000000;$i++) {
my $a = test::hello();
}
C++ code:
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include <stdio.h>
char* create_mem() {
char *foo = (char*)malloc(sizeof(char)*150);
return foo;
}
XS code:
MODULE = test PACKAGE = test
char * hello()
CODE:
RETVAL = create_mem();
OUTPUT:
RETVAL
CLEANUP:
free(RETVAL);
I'm afraid that the people who wrote (and write) the Perl XS documentation probably consider it too obvious that Perl cannot magically detect memory allocation made in other languages (like C++) to document that explicitly. There's a bit in the perlguts documentation page that says that all memory to be used via the Perl XS API must use Perl's macros to do so that may help you argue.
When you write XS code, you're writing C (or sometimes C++) code. You still need to write proper C/C++, which includes deallocating allocated memory when appropriate.
The glue function you desire XS to create is the following:
void hello() {
dSP; // Declare and init SP, the stack pointer used by mXPUSHs.
char* mem = create_mem();
mXPUSHs(newSVpv(mem, 0)); // Create a scalar, mortalize it, and push it on the stack.
free(mem); // Free memory allocated by create_mem().
XSRETURN(1);
}
newSVpv makes a copy of mem rather than taking possession of it, so the above clearly shows that free(mem) is needed to deallocate mem.
In XS, you could write that as
void hello()
CODE:
{ // A block is needed since we're declaring vars.
char* mem = create_mem();
mXPUSHs(newSVpv(mem, 0));
free(mem);
XSRETURN(1);
}
Or you could take advantage of XS features such as RETVAL and CLEANUP.
SV* hello()
char* mem; // We can get rid of the block by declaring vars here.
CODE:
mem = create_mem();
RETVAL = newSVpv(mem, 0); // Values returned by SV* subs are automatically mortalized.
OUTPUT:
RETVAL
CLEANUP: // Happens after RETVAL has been converted
free(mem); // and the converted value has been pushed onto the stack.
Or you could also take advantage of the typemap, which defines how to convert the returned value into a scalar.
char* hello()
CODE:
RETVAL = create_mem();
OUTPUT:
RETVAL
CLEANUP:
free(RETVAL);
All three of these are perfectly acceptable.
A note on mortals.
Mortalizing is a delayed reference count decrement. If you were to decrement the SV created by hello before hello returns, it would get deallocated before hello returns. By mortalizing it instead, it won't be deallocated until the caller has a chance to inspect it or take possession of it (by increasing its reference count).
I have a big NSDictionary full of entries that are all of type NSData. I have several entries that need to be of type int32_t however I am not 100% sure how to copy the data in the entries of the NSDictionary across..
is it as simple as doing the following -
.h
//..
int32_t myint;
}
#property (assign) int32_t myint;
//..
.m
//..
#synthesize cardID;
//..
- (void)assignSearchData:(NSData*)searchData
{
myint = [searchData objectForKey:#"IntKey"];
}
//..
or do I need some type of data conversion inside my method?
and a quick side question, have I even declared the int32_t correctly? I have looked for an example in the docs and on here but am struggling to find one.
Well, you can access the raw bytes in the data object directly.
void const *dataPtr = [data bytes];
Now that you have a pointer to raw memory, you can copy it any way you want (these rules apply to any data transfer, not just iOS). If you need to consider alignment boundaries, you need to use memcpy.
int32_t myInt;
memcpy(&myInt, dataPtr);
Otherwise, if on an architecture that allows integer manipulation across alignment boundaries...
int32_t myInt = *(int32_t const *)dataPtr;
Now, ARM supports access across alignment boundaries, but it's much slower. I have not done a performance comparison, but you are not continuing to use the mal-alignged pointer, so it may be better than the memcpy function call (though, to be honest, that is probably way too much performance consideration for you).
The biggest concern is byte-order of the data. If it's provided by you, then do whatever you want, but you should prefer one standard.
If it's coming from a third party, it's probably in network byte order (aka big-endian). You may need to convert to your host endian representation. Fortunately, that's straight forward with hton and ntoh and their friends.
FWIW, Intel is little-endian, and network-byte-order is big-endian, modern Macs and iOS devices are little-endian, older Macs are big-endian.
// Convert from network order to host order.
// Does the right thing wherever your code is running
myInt = ntohl(myInt);
In short, either...
int32_t myInt = ntohl(*(int32_t const *)[data bytes]);
or
int32_t myInt;
memcpy(&myInt, [data bytes);
myInt = ntohl(myInt);
So, the data has to get in there somehow. It's, the inverse...
int32_t myInt = 42;
myInt = htonl(myInt);
NSData *data = [NSData dataWithBytesNoCopy:&myInt length:sizeof(myInt) freeWhenDone:NO];
Of course, use the right Data initializer... that one will just use those raw bytes on the stack, so you better not use it after the stack unwinds.
You don't have to worry about alignment on the data you send, unless you are guaranteeing the receiver that the data will be aligned to some boundary.
Yes, int32_t is fine. So you have a stream of byes. What you need to know is what he layout of the bytes are. It you know what the data is it will be pretty easy to construct it.
Given a NSData object with a length of 4 (size of int32_t), then you would :
int32_t val;
if([data length] == sizeof(uint32_t)) {
void *bytes = [data bytes];
// if the layout is same as iOS then
memcpy(&val, bytes, sizeof(int32_t) );
}
if that is not the case, then you can try:
unsigned char val[4] = {0,0,0,0};
if([data length] == sizeof(uint32_t)) {
memcpy(val, bytes, sizeof(int32_t) );
then rearrange the bytes
}
I am coding an audio app for the iphone where I need to use some C code to deal with the audio files. In short, I have a memory leak that is causing the app to crash after so many files have been loaded. The problem is related to a Struct that I create that holds the audio files when read in. The Struct is created as follows;
typedef struct {
UInt32 frameCount; // the total number of frames in the audio data
UInt32 sampleNumber; // the next audio sample to play
BOOL isStereo; // set to true if there is data audioDataRight member
AudioUnitSampleType *audioDataLeft; // complete left channel of audio data read from file
AudioUnitSampleType *audioDataRight; // complete right channel of audio data read file
} soundStruct, *soundStructPtr;
The Struct is then Initialized in the header like this;
soundStruct phraseSynthStructArray[3];
I then attempt to join two files that have been read into phraseSynthStructArray[phrase1Index] and phraseSynthStructArray[phrase2Index] and put the combined file into phraseSynthStructArray[synthPhraseIndex] like this;
- (BOOL) joinPhrases:(UInt32)phrase1Index phrase2Index:(UInt32)phrase2Index synthPhraseIndex:(UInt32)synthPhraseIndex{
// get the combined frame count
UInt64 totalFramesInFile = inArray[phrase1Index].frameCount + inArray[phrase2Index].frameCount;
//now resize the synthPhrase slot buffer to be the same size as both files combined
// phraseOut is used to hold the combined data prior to it being passed into the soundStructArray slot
free(phraseSynthStructArray[synthPhraseIndex].audioDataLeft);
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = NULL;
phraseSynthStructArray[synthPhraseIndex].frameCount = 0;
phraseSynthStructArray[synthPhraseIndex].frameCount = totalFramesInFile;
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType));
for (UInt32 frameNumber = 0; frameNumber < inArray[phrase1Index].frameCount; ++frameNumber) {
phraseSynthStructArray[synthPhraseIndex].audioDataLeft[frameNumber] = phraseSynthStructArray[phrase1Index].audioDataLeft[frameNumber];
}
UInt32 sampleNumber=0;
for (UInt32 frameNumber = phraseSynthStructArray[phrase1Index].frameCount; frameNumber < totalFramesInFile; ++frameNumber) {
phraseSynthStructArray[synthPhraseIndex].audioDataLeft[frameNumber] = phraseSynthStructArray[phrase2Index].audioDataLeft[sampleNumber];
sampleNumber++;
}
return YES;
}
This all works fine and the resulting file is joined and can be used. The isuue I am having is when I allocate the memory here, phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType)); then next time the method is called, this memory leaks each time and eventually crashes the app. The reason I need to allocate the memory here is because the memory has to be resized to accomodate the joined file which varies in length depending on the size of the input files.
I cannot free the memory after the operation as its needed elsewhere after the method has been called and I have tried to free it before (in joinPhrases method above), but this does not seem to work. I have also tried using realloc to free/reallocate the memory by passing the pointer to the previously allocated memory but this casues a crash stating EXEC_BAD_ACCESS.
I am not a seasoned C programmer and Cannot figure out what I am doing wrong here to cause the leak. I would appreciate some advice to help me track down this issue as I have been banging my head against this for days with no joy. I have read thats its a bad idea to have Pointers in Structs, could this be the root of my problem?
Thanks in advance,
K.
Maybe this helps:
- (BOOL) joinPhrases:(UInt32)phrase1Index phrase2Index:(UInt32)phrase2Index synthPhraseIndex:(UInt32)synthPhraseIndex{
// get the combined frame count
UInt64 totalFramesInFile = inArray[phrase1Index].frameCount + inArray[phrase2Index].frameCount;
. . .
void* old_ptr = phraseSynthStructArray[synthPhraseIndex].audioDataLeft;
phraseSynthStructArray[synthPhraseIndex].audioDataLeft = (AudioUnitSampleType *) calloc(totalFramesInFile, sizeof (AudioUnitSampleType));
if( old_ptr ) free(old_ptr);
. . .
return YES;
}
And make sure that there is no garbage in phraseSynthStructArray[synthPhraseIndex]
When converting a NSString to a char* using UTF8String, how to retain it?
According to the following link, when you use UTF8String the returned char* is pretty much autoreleased, so it won't last beyond the current function: http://developer.apple.com/mac/library/documentation/cocoa/reference/Foundation/Classes/NSString_Class/Reference/NSString.html#jumpTo_128
It says i have to copy it or something to keep it around. How can i do this?
The reason i ask is that if i do [myCharPointer retain] it doesn't retain it because it's not an obj-c object, it's a c pointer.
Thanks
You can use strdup()
const char* utf8Str = [#"an example string" UTF8String];
if (utf8Str != NULL)
{
stringIWantToKeep = strdup(utf8Str);
}
When you are done with stringIWantToKeep, you free it as though it was originally malloc'd.
Try using -getCString:maxLength:encoding:, e.g.:
NSUInteger bufferCount = sizeof(char) * ([string length] + 1);
const char *utf8Buffer = malloc(bufferCount);
if ([string getCString:utf8Buffer
maxLength:bufferCount
encoding:NSUTF8StringEncoding]) {
NSLog("Success! %s", utf8Buffer);
free(utf8Buffer); // Remember to do this, or you will get a memory leak!
}
If you need an object to retain/release as every other object you can do the following:
NSData* storage= [yourNSString dataUsingEncoding:NSUTF8StringEncoding];
char* yourCString= (char*)storage.bytes;
// your code flow here
Now you can pass both storage and yourCString to any function retaining/releasing storage as you like, when the retain count of storage will go to 0 the memory pointed by yourCString will be freed too.
I used this to keep a single copy of a very long string while having references created by strtok_r in beans and have the memory released only when all beans had been released.
A little note about (missing) BOM:
As stated here http://boredzo.org/blog/archives/2012-06-03/characters-in-nsstring dataUsingEncoding: should add BOM but i've checked with the debugger and there is no BOM in the returned bytes.
Disclaimer: I am an Xcode / iPhone SDK Noob.
I am trying to establish a client-side TCP/IP connection to an existing server. Upon connection, I expect to receive some data about the server (version, etc.).
When my connection is made, the NSStreamEventOpenCompleted event fires, so I know the connection is made. Next the NSStreamEventHasBytesAvailable event fires and I am executing the following code. The value 71 (int) is stored in len, which I believe is correct. However, the line
[data appendBytes:&buffer length:len];
is crashing (I think). There is no actual error thrown but I do see __TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__ even though I have clearly added error catching:
case NSStreamEventHasBytesAvailable:
{
NSMutableData *data=[[NSMutableData alloc] init];
uint8_t *buffer[1024];
unsigned int len=0;
len=[(NSInputStream *)stream read:buffer maxLength:1024];
if(len>0){
#try{
[data appendBytes:&buffer length:len];
}
#catch(NSException *ex){
NSLog(#"Fail: %#", ex);
}
[statusLabel setText:[data stringValue]];
//[bytesRead setIntValue:[bytesRead intValue]+len];
}else{
NSLog(#"No Buffer");
}
break ;
}
This is a problem down at the C level: you're confused about buffers and pointers.
This code:
uint8_t *buffer[1024];
gives you a stack buffer of 1024 pointers to uint8_ts, which is almost certainly not what you want. Instead:
uint8_t buffer[1024];
Later on, you're passing the address of your pointer on the stack to -[NSMutableData appendBytes:length:], which again is not what you want: as in the documentation, pass the first element:
[data appendBytes:buffer length:len];
There's a very thorough programming guide with complete code for what you're trying to do, you may want to reference it.
As for __TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION__, memory corruption and bad pointer dereferencing isn't something you can catch with an Objective-C #try/#catch; it's much lower-level. On the other hand, you can still catch this in the debugger if you turn debugging on.
declare your buffer as:
uint8_t buffer[1024];
and do the append as:
[data appendBytes:buffer length:len];
For completeness read:maxLength: returns an NSInteger and will be negative if there was an error. Assigning it to an unsigned int discards this and can cause a crash.