Best way to release memory allocated using malloc - objective-c

I have function to convert an integer into byte array (for iPhone). To add dynamicity I have allocate the array using malloc. But I think this will leak memory. What's best way to manage this memory,
+ (unsigned char *) intToByteArray:(int)num{
unsigned char * arr = (unsigned char *)
malloc(sizeof(num) * sizeof(unsigned char));
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
arr[i] = num & 0xFF;
num = num >> 8;
}
return arr;
}
When calling,
int x = 500;
unsigned char * bytes = [Util intToByteArray:x];
I want to avoid the call free(bytes) since, the calling function do not know or explicitly knows, the memory is allocated and not freed.

A few things:
The char type (and signed char and unsigned char) all have a size of 1 by definition, so sizeof(unsigned char) is unnecessary.
It looks like you just want to get the byte representation of an int object, if this is the case, it is not necessary to allocate more space for it, simply take the address of the int and cast it to a pointer to unsigned char *. If the byte order is wrong you can use the NSSwapInt function to swap the order of the bytes in the int and then take the address and cast to unsigned char *. For example:
int someInt = 0x12345678;
unsigned char *bytes = (unsigned char *) &someInt;
This cast is legal and reading from bytes is legal up until sizeof(int) bytes are read. This is accessing the “object representation”.
If you insist on using malloc, then you simply need to pass the buffer to free when you are done, as in:
free(bytes);
The name of your method does not imply the correct ownership of the returned buffer. If your method returns something that the caller is responsible for freeing, it is conventional to name the method using new, copy, or sometimes create. A more suitable name would be copyBytesFromInt: or something similar. Otherwise you could have the method accept a pre-allocated buffer and call the method getBytes:fromInt:, for example:
+ (void) getBytes:(unsigned char *) bytes fromInt:(int) num
{
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
bytes[i] = num & 0xFF;
num = num >> 8;
}
}
You could wrap your bytes into a NSData instance:
NSData *data = [NSData dataWithBytesNoCopy:bytes length:sizeof(num) freeWhenDone:YES];
Make sure your method follows the usual object ownership rules.

Just call free(bytes); when you are done with the bytes (either at the end of method or in dealloc of the class)
since you want to avoid the free call, you could wrap your byte[] in a NSData object:
NSData *d = [NSData dataWithBytesNoCopy:bytes length:num freeWhenDone:YES];

The conventional way of handling this is for the caller to pass in an allocated byte buffer. That way the caller is responsible for freeing it. Something like:
int x = 500;
char *buffer = malloc(x * sizeof(char));
[Util int:x toByteArray:buffer];
…
free(buffer);
I would also consider creating an NSData to hold the bytes, this would take care of memory management for you, while still allowing you to alter the byte buffer:
+ (NSData *) intToByteArray:(int)num {
unsigned char * arr = (unsigned char *)
malloc(sizeof(num) * sizeof(unsigned char));
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
arr[i] = num & 0xFF;
num = num >> 8;
}
return [NSData dataWithBytesNoCopy:arr length:num freeWhenDone:YES];
}

Related

Returning variable size byte array and free the memory

I am writing a proxy .c file for using OpenSSL library for RSA encryption. Usable for iPhone. Since encrypted data sized is not known to the calling class in Objective C, the container is not initialized and I want to keep it dynamic. The char array and the received size is called by reference. Its memory is dynamically allocated in ssl_encrypt_public_rsa and the caller has to free it. I don't like the idea to give the responsibility to the caller.
Is there any other robust method that you can suggest?
openssl implementation in .c (later compiled to static lib .a file)
// calling function must free cipherText memory
void ssl_encrypt_public_rsa(RSA *rsaKey, int plainLength, unsigned char *plainText,
int *cipherLength, unsigned char **cipherText)
{
int enc_len = RSA_size(rsaKey);
unsigned char *enc_bytes = malloc(enc_len * sizeof(char));
int encSize = RSA_public_encrypt(plainLength, plainText, enc_bytes, rsaKey, RSA_PKCS1_PADDING);
*cipherText = enc_bytes;
*cipherLength = encSize;
}
void ssl_encrypt_mips(int plainLength, unsigned char *plainText,
int *cipherLength, unsigned char **cipherText)
{
// rsaKeyMips is defined and initialized earlier
ssl_encrypt_public_rsa(rsaKeyMips, plainLength, plainText, cipherLength, cipherText);
}
Calling function Objective C .m file
-(NSData *) encryptMips:(NSData *)inData
{
int encSize = 0;
unsigned char *cipherBytes;
ssl_encrypt_mips((int)inData.length, (unsigned char *)inData.bytes, &encSize, &cipherBytes);
if (encSize == -1 ) return nil;
NSData * d = [NSData dataWithBytes:cipherBytes length:encSize];
free(cipherBytes);
return d;
}
It is unclear what you are asking, as you've already wrapped the C call in a wrapper which takes care of the free(). If you wish to remove the free() from your wrapper, and serendipitously avoid a copy, you can change your:
NSData *d = [NSData dataWithBytes:cipherBytes length:encSize];
free(cipherBytes);
to:
NSData *d = [NSData dataWithBytesNoCopy:cipherBytes length:encSize free:YES];
which hands ownership of the malloc() block to the NSData instance, which will free() it later when no longer needed.
HTH

Troubles with casting bytes from NSInputStream?

I have openssl server and Objective-C client. I send message like this
uint32_t testD = 161;
err = SSL_write(ssl_, &testD, sizeof(uint32_t));
and read it by NSInputStream like
case NSStreamEventHasBytesAvailable:
{
uint8_t buffer[4];
int len;
while ([inStream hasBytesAvailable])
{
len = [inStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
NSData *theData = [[NSData alloc] initWithBytes:buffer length:len];
if (nil != output)
{
char buff;
[theData getBytes:&buff length:1];
uint32_t temp = (uint32_t)buffer;
}
...
So, in output I have "¡", it's 161-th ASCII symbol, in buff I have '\xa1' and in temp very big number, but actually I need 161 in temp.
I read that '\xa1' it's also 161, but I can't cast this to uint32_t.
What is the problem?
ANSWER:
The problem was in casting. This works fine for me:
unsigned char buff;
int temp = buff;
or
char buff;
int b = (unsigned char) buff;
No encoding is used by SSL_write(), and \xa1 == 161 is a mathematical identity, not the result of any encoding process. As you're successfully recovering \xa1, clearly no decoding is used by NSInputStream either.
It seems to me that you're casting the address of the buffer rather than its contents, which is why you get a high value that varies with compilation.
In addition you are possibly over-running the data by reading whatever is available and then only consuming four bytes of it: less in fact because you're incorrectly testing len >= 1 rather than len >= 4.
You should:
Use a buffer of exactly four bytes. No need to allocate it dynamically: you can declare it as a local array.
Read until you have read four bytes. This requires a loop.
Change the casting syntax (don't ask me how, I'm no Objective-C expert, but the code that recovers buff looks like a good start), so that you get the content of the buffer instead of the address.
After that you may then have endian issues.
Nothing to do with encoding.
What encoding is used in SSL_write and NSInputStream?
There is no encoding. Its bytes in and bytes out.
I think you are looking for network byte order/endianess.
Network byte order is big endian. So your code would become:
uint32_t testD = 161;
uint32_t be = htonl(testD);
err = SSL_write(ssl_, &be, sizeof(be));
Here's the description of htonl from the htonl(3) man pages:
The htonl() function converts the unsigned integer hostlong from host byte order to network byte order.
To convert back, you would use ntohl.
I'm not sure if Cocoa/CocoaTouch offers a replacement for htonl and ntohl. So you might have to use them in your iPhone projects, too. See, for example, Using ntohl and htonl problems on iPhone.
We can get a single byte value like this:
unsigned char buff;
int temp = buff;
Or
char buff;
int b = (unsigned char) buff;

Arbitrary precision bit manipulation (Objective C)

I need to do bit operations on representations of arbitrary precision numbers in Objective C. So far I have been using NSData objects to hold the numbers - is there a way to bit shift the content of those? If not, is there a different way to achieve this?
Using NSMutableData you can fetch the byte in a char, shift your bits and replace it with -replaceBytesInRange:withBytes:.
I don't see any other solution except for writing your own date holder class using a char * buffer to hold the raw data.
As you'll have spotted, Apple doesn't provide arbitrary precision support. Nothing is provided larger than the 1024-bit integers in vecLib.
I also don't think NSData provides shifts and rolls. So you're going to have to roll your own. E.g. a very naive version, which may have some small errors as I'm typing it directly here:
#interface NSData (Shifts)
- (NSData *)dataByShiftingLeft:(NSUInteger)bitCount
{
// we'll work byte by byte
int wholeBytes = bitCount >> 3;
int extraBits = bitCount&7;
NSMutableData *newData = [NSMutableData dataWithLength:self.length + wholeBytes + (extraBits ? 1 : 0)];
if(extraBits)
{
uint8_t *sourceBytes = [self bytes];
uint8_t *destinationBytes = [newData mutableBytes];
for(int index = 0; index < self.length-1; index++)
{
destinationBytes[index] =
(sourceBytes[index] >> (8-extraBits)) |
(sourceBytes[index+1] << extraBits);
}
destinationBytes[index] = roll >> (8-extraBits);
}
else
/* just copy all of self into the beginning of newData */
return newData;
}
#end
Of course, that assumes the number of bits you want to shift by is itself expressible as an NSUInteger, amongst other sins.

Enumerate NSString characters via pointer

How can I enumerate NSString by pulling each unichar out of it? I can use characterAtIndex but that is slower than doing it by an incrementing unichar*. I didn't see anything in Apple's documentation that didn't require copying the string into a second buffer.
Something like this would be ideal:
for (unichar c in string) { ... }
or
unichar* ptr = (unichar*)string;
You can speed up -characterAtIndex: by converting it to it's IMP form first:
NSString *str = #"This is a test";
NSUInteger len = [str length]; // only calling [str length] once speeds up the process as well
SEL sel = #selector(characterAtIndex:);
// using typeof to save my fingers from typing more
unichar (*charAtIdx)(id, SEL, NSUInteger) = (typeof(charAtIdx)) [str methodForSelector:sel];
for (int i = 0; i < len; i++) {
unichar c = charAtIdx(str, sel, i);
// do something with C
NSLog(#"%C", c);
}
EDIT: It appears that the CFString Reference contains the following method:
const UniChar *CFStringGetCharactersPtr(CFStringRef theString);
This means you can do the following:
const unichar *chars = CFStringGetCharactersPtr((__bridge CFStringRef) theString);
while (*chars)
{
// do something with *chars
chars++;
}
If you don't want to allocate memory for coping the buffer, this is the way to go.
Your only option is to copy the characters into a new buffer. This is because the NSString class does not guarantee that there is an internal buffer you can use. The best way to do this is to use the getCharacters:range: method.
NSUInteger i, length = [string length];
unichar *buffer = malloc(sizeof(unichar) * length);
NSRange range = {0,length};
[string getCharacters:buffer range:range];
for(i = 0; i < length; ++i) {
unichar c = buffer[i];
}
If you are using potentially very long strings, it would be better to allocate a fixed size buffer and enumerate the string in chunks (this is actually how fast enumeration works).
I created a block-style enumeration method that uses getCharacters:range: with a fixed-size buffer, as per ughoavgfhw's suggestion in his answer. It avoids the situation where CFStringGetCharactersPtr returns null and it doesn't have to malloc a large buffer. You can drop it into an NSString category, or modify it to take a string as a parameter if you like.
-(void)enumerateCharactersWithBlock:(void (^)(unichar, NSUInteger, BOOL *))block
{
const NSInteger bufferSize = 16;
const NSInteger length = [self length];
unichar buffer[bufferSize];
NSInteger bufferLoops = (length - 1) / bufferSize + 1;
BOOL stop = NO;
for (int i = 0; i < bufferLoops; i++) {
NSInteger bufferOffset = i * bufferSize;
NSInteger charsInBuffer = MIN(length - bufferOffset, bufferSize);
[self getCharacters:buffer range:NSMakeRange(bufferOffset, charsInBuffer)];
for (int j = 0; j < charsInBuffer; j++) {
block(buffer[j], j + bufferOffset, &stop);
if (stop) {
return;
}
}
}
}
The fastest reliable way to enumerate characters in an NSString I know of is to use this relatively little-known Core Foundation gem hidden in plain sight (CFString.h).
NSString *string = <#initialize your string#>
NSUInteger stringLength = string.length;
CFStringInlineBuffer buf;
CFStringInitInlineBuffer((__bridge CFStringRef) string, &buf, (CFRange) { 0, stringLength });
for (NSUInteger charIndex = 0; charIndex < stringLength; charIndex++) {
unichar c = CFStringGetCharacterFromInlineBuffer(&buf, charIndex);
}
If you look at the source code of these inline functions, CFStringInitInlineBuffer() and CFStringGetCharacterFromInlineBuffer(), you'll see that they handle all the nasty details like CFStringGetCharactersPtr() returning NULL, CFStringGetCStringPtr() returning NULL, defaulting to slower CFStringGetCharacters() and caching the characters in a C array for fastest access possible. This API really deserves more publicity.
The caveat is that if you initialize the CFStringInlineBuffer at a non-zero offset, you should pass a relative character index to CFStringInlineBuffer(), as stated in the header comments:
The next two functions allow fast access to the contents of a string, assuming you are doing sequential or localized accesses. To use, call CFStringInitInlineBuffer() with a CFStringInlineBuffer (on the stack, say), and a range in the string to look at. Then call CFStringGetCharacterFromInlineBuffer() as many times as you want, with a index into that range (relative to the start of that range). These are INLINE functions and will end up calling CFString only once in a while, to fill a buffer. CFStringGetCharacterFromInlineBuffer() returns 0 if a location outside the original range is specified.
I don't think you can do this. NSString is an abstract interface to a multitude of classes that make no guarantees about the internal storage of the character data, so it's entirely possible there is no character array to get a pointer to.
If neither of the options mentioned in your question are suitable for your app, I'd recommend either creating your own string class for this purpose, or using raw malloc'ed unichar arrays instead of string objects.
This will work:
char *s = [string UTF8String];
for (char *t = s; *t; t++)
/* use as */ *t;
[Edit] And if you really need unicode characters then you have no option but to use length and characterAtIndex. From the documentation:
The NSString class has two primitive methods—length and characterAtIndex:—that provide the basis for all other methods in its interface. The length method returns the total number of Unicode characters in the string. characterAtIndex: gives access to each character in the string by index, with index values starting at 0.
So your code would be:
for (int index = 0; index < string.length; index++)
{
unichar c = [string characterAtIndex: index];
/* ... */
}
[edit 2]
Also, don't forget that NSString is 'toll-free bridged' to CFString and thus all the non-Objective-C, straight C-code interface functions are usable. The relevant one would be CFStringGetCharacterAtIndex

Packing ints to bytes (NSData)

I want to pack a MIDI message into an NSData object.
int messageType = 3; // 0-15
int channel = 5; // 0-15
int data1 = 56; // 0-127
int data2 = 78; // 0-127
int packed = data2;
packed += data1 * 127;
packed += channel * 16129; // 127^2
packed += messageType * 258064; // 127^2 * 16
NSLog(#"packed %d", packed);
NSData *packedData = [NSData dataWithBytes:&packed length:sizeof(packed)];
int recovered;
[packedData getBytes:&recovered];
NSLog(#"recovered %d", recovered);
This works wonderfully and while I'm proud of myself, I know that the conversion to bytes is not done correctly: it should be a direct conversion without a lot of addition and multiplication. How can that be done?
Edit: I'm now aware that I can just do this
char theBytes[] = {messageType, channel, data1, data2};
NSData *packedData = [NSData dataWithBytes:&theBytes length:sizeof(theBytes)];
and on the Java side
byte[] byteBuffer = new byte[4]; // Receive buffer
while (in.read(byteBuffer) != -1) {
System.out.println("data2=" + byteBuffer[3]);
}
and it will work, but I'd like the solution to get an NSData with just 3 bytes.
Personally, I would go for an NSString:
NSString *dataString = [NSString stringWithFormat:#"%i+%i+%i+%i", messageType, channel, data1, data2];
NSData *packedData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
Easy to use, and easy to transfer. Unpacking is a tiny bit more complicated, but not difficult at all either.
NSScanner *scanner = [NSScanner scannerWithString:[[[NSString alloc] initWithData:packedData encoding:NSUTF8StringEncoding] autorelease]];
int messageType, channel, data1, data2;
[scanner scanInt:&messageType];
[scanner scanInt:&channel];
[scanner scanInt:&data1];
[scanner scanInt:&data2];
Here's a 3-byte solution that I put together.
char theBytes[] = {message_type * 16 + channel, data1, data2};
NSData *packedData = [NSData dataWithBytes:&theBytes length:sizeof(theBytes)];
char theBytesRecovered[3];
[packedData getBytes:theBytesRecovered];
int messageTypeAgain = (int)theBytesRecovered[0]/16;
int channelAgain = (int)theBytesRecovered[0] % 16;
int data1Again = (int)theBytesRecovered[1];
int data2Again = (int)theBytesRecovered[2];
NSLog(#"packed %d %d %d %d", messageTypeAgain, channelAgain, data1Again, data2Again);
and on the other side of the wire, this is just as easy to pick up, because each byte is a byte. I just finished trying this on the iOS side and the Java side, and there are no problems on either. There is no problem with endian-ness, because each integer fits into one single byte (or two in one byte, in one case).
you have several options.
since it looks like you want a contiguous glob of data in the NSData representation...
you'll want to create a packed struct, and pass the data to the NSData call as a predefined endianness (so both ends know how to unarchive the data glob).
/* pack this struct's ivars and and enable -Wreorder to sanity check that the compiler does not reorder members -- i see no reason for the compiler to do this since the fields are equal size/type */
struct t_midi_message {
UInt8 message_type; /* 0-15 */
UInt8 channel; /* 0-15 */
UInt8 data1; /* 0-127 */
UInt8 data2; /* 0-127 */
};
union t_midi_message_archive {
/* members - as a union for easy endian swapping */
SInt32 glob;
t_midi_message message;
enum { ValidateSize = 1 / (4 == sizeof(t_midi_message)) };
/* nothing unusual here, although you may want a ctor which takes NSData as an argument */
t_midi_message_archive();
t_midi_message_archive(const t_midi_message&);
t_midi_message_archive(const t_midi_message_archive&);
t_midi_message_archive& operator=(const t_midi_message_archive&);
/* swap routines -- just pass #member glob to the system's endian routines */
void swapToNativeEndianFromTransferEndian();
void swapToTransferEndianFromNativeEndian();
};
void a(const t_midi_message_archive& msg) {
t_midi_message_archive copy(msg);
copy.swapToTransferEndianFromNativeEndian();
NSData * packedData([NSData dataWithBytes:&copy.glob length:sizeof(copy.glob)]);
assert(packedData);
t_midi_message_archive recovered;
[packedData getBytes:&recovered.glob];
recovered.swapToNativeEndianFromTransferEndian();
/* recovered may now be used safely */
}