iOS a Very Amazing(malloc_error_break) - ios

first this my code
#pragma pack (4)
typedef struct _Login{
char user[32];
char pwd[32];
int userID;
}Login,*PLogin;
const unsigned long MSG_TAG_HEADER_YXHY = 0x59485859;
#pragma pack (2)
typedef struct tagTcpPacketHeader
{
int ulHtag;
char ucVersion;
char ucCmd;
int ulUserId;
short usPacketNum;
int ulDataLen;
}TcpPacketHeader,*LPTcpPacketHeader;
#pragma pack ()
const unsigned int TCP_HEADER_PACKET_LEN = sizeof(TcpPacketHeader);
- (NSData*)sendDataFileWithUserId:(const int)nUserId nCmd:(const int)nCmd pData:(NSData*)data{
NSData* sendData;
void* sendObj = malloc(data.length);
[data getBytes:sendObj length:data.length];
static int nPacketNum = 0;
int nLen = (int)data.length + TCP_HEADER_PACKET_LEN;
char *pTmpBuf = malloc(nLen);
LPTcpPacketHeader tcpHeader = (LPTcpPacketHeader)pTmpBuf;
tcpHeader->ulHtag = MSG_TAG_HEADER_YXHY;
tcpHeader->ucVersion = 1;
tcpHeader->ucCmd = nCmd;
tcpHeader->ulUserId = nUserId;
tcpHeader->usPacketNum = nPacketNum;
tcpHeader->ulDataLen = nLen;
memcpy(tcpHeader + TCP_HEADER_PACKET_LEN,sendObj, data.length);
sendData = [NSData dataWithBytes:pTmpBuf length:nLen];
nPacketNum++;
free(pTmpBuf);
free(sendObj);
return sendData;
}
- (NSData*)get_File_Login:(NSString*)userID{
int length = sizeof(Login);
Login log_in = {"123","456",userID.intValue};
NSData* login_data = [NSData dataWithBytes:&log_in length:length];
NSData* ret = [self sendDataFileWithUserId:log_in.userID nCmd:5 pData:login_data];
return ret;
}
Use
NSData* ms = [self get_File_Login:#"123"];
NSLog(#"%#",ms);
After frequent use can be a problem
question
This question makes me very headache why appear “ set a breakpoint in malloc_error_break to debug ”
I have added the "malloc_error_break" the breakpoint,But it doesn't work......
Who can tell me the answer???

When you use the pointer in memcpy this way
memcpy(tcpHeader + TCP_HEADER_PACKET_LEN,sendObj, data.length);
this means that you want to copy into memory location pointed by tcpHeader plus TCP_HEADER_PACKET_LEN times the size of the data the pointer points to. It is the same as doing &tcpHeader[TCP_HEADER_PACKET_LEN].
Assuming you want to write to a location right after the header there are two ways to fix it:
1) use a pointer with a size of 1, meaning a char*. In your code you have a pointer pTmpBuf that is such so just change the code to:
memcpy(pTmpBuf + TCP_HEADER_PACKET_LEN, sendObj, data.length);
2) use the size 1 for this calculation. Since the size of the data it points to is the same as TCP_HEADER_PACKET_LEN then multiplying it by one gives the correct location:
memcpy(tcpHeader + 1, sendObj, data.length);
I would recommend the first since it's clear what you are calculating. In the second it is unclear why you would add one, as well as using a pointer to one type when copying data that isn't that type.

Related

Builtin MemCpy Chk will always overflow destination buffer

Updating my app from 32-bit to 64-bit.
According to the Apple Documentation floats are only 4 byte and I need to use CGFloat (8 byte)
I am using the memcpy to read in bytes. I have updated all my sizeof(float)s to sizeof(CGFloat).
But when I do I get the Semantic issue
__builtin___memcpy_chk will always overflow destination buffer. Expanded from macro memcpy
I updated my NSData readDataOfLenght to take sizeof(CGFloat) and it seems to work ok. Sometimes not all the data that is read in is correct.
I am afraid I am over my head in this and could use some help.
-(void) readByteData:(NSFileHandle *)fHandle Size:(NSInteger)byteSize
{
[super readByteData:fHandle Size:byteSize];
NSData *data = [fHandle readDataOfLength:sizeof(CGFloat)];
float r;
memcpy(&r, [data bytes], sizeof(CGFloat));
self.radius = r;
int nCGPointSize = sizeof(CGFloat) * 2;
data = [fHandle readDataOfLength:nCGPointSize];
float xy[2];
memcpy(xy, [data bytes], nCGPointSize);
self.centerPos = ccp(xy[0], xy[1]);
data = [fHandle readDataOfLength:sizeof(CGFloat)];
float start_angle;
memcpy(&start_angle, [data bytes], sizeof(CGFloat));
self.startAngle = start_angle;
data = [fHandle readDataOfLength:sizeof(CGFloat)];
float end_angle;
memcpy(&end_angle, [data bytes], sizeof(CGFloat));
self.endAngle = end_angle;
data = [fHandle readDataOfLength:sizeof(int)];
int d;
memcpy(&d, [data bytes], sizeof(int));
self.dir = d;
flagClosed = YES;
}
This instruction:
float r;
memcpy(&r, [data bytes], sizeof(CGFloat));
Tells your compiler:
Read sizeof(CGFloat) (== 8 bytes!) from the location [data bytes]
and write them to r
But r is only 4 bytes in size! So the first 4 bytes are written to r and the next 4 bytes are written to whatever follows r in memory and this is not allowed. memcpy is a simple byte copy instructions, it moves any number of bytes from memory location A to memory location B, it cannot convert data types for you. If you need to convert CGFloat values to float values, then you actually need to do that conversion yourself.
CGFloat bigR;
memcpy(&bigR, [data bytes], sizeof(bigR));
self.radius = (float)bigR;
Same when reading multiple values:
CGFloat bigXY[2];
data = [fHandle readDataOfLength:sizeof(bigXY)];
memcpy(bigXY, [data bytes], sizeof(bigXY));
self.centerPos = ccp((float)bigXY[0], (float)bixXY[1]);
The casts are only to make it more clear where the conversion takes place, most compilers will also compile the code without all the (float) casts and without complaining.
As a general rule:
memcpy(dst, src, size)
size must never be bigger than the memory src points to or the memory dst points to. In your case, size was always bigger than the memory dst pointed to.
So far the explanation why your code didn't work. However, you actually don't need to use memcpy at all as if you have a memory block out of multiple values of a known data type, of course you can access that memory directly without having to copy it anywhere:
NSData * data = [fHandle readDataOfLength:sizeof(CGFloat)];
if (!data) {
// ... handle errorr ...
}
const CGFloat * cgfloatsInData = (const CGFloat *)[data bytes];
self.radius = (float)cgfloatsInData[0];
data = [fHandle readDataOfLength:sizeof(CGFloat) * 2];
if (!data) {
// ... handle errorr ...
}
const CGFloat * cgfloatsInData = (const CGFloat *)[data bytes];
self.centerPos = ccp((float)cgfloatsInData[0], (float)cgfloatsInData[1]);
And so on. But this is highly inefficient, as you seem to always expect some fixed size structure with no optional values, so why not reading it as a structure? That way you only need one I/O access to read all of it and only one NSData object must be created by the system.
const struct {
CGFloat radius;
CGFloat xCoord;
CGFloat yCoord;
CGFloat startAngle;
CGFloat endAngle;
int dir;
} __attribute__((packed)) * entry;
// `const` as the memory `entry` will point to will be read-only.
// `* entry` means entry is a pointer to memory of a struct
// that looks as described above. __attribute__((packed)) means
// the memory must be laid out exactly as shown above and have no
// padding for better alignment of fields.
NSData * data = [fHandle readDataOfLength:sizeof(*entry)];
// `sizeof(*entry)` means the size of the memory entry points to,
// contrary to `sizeof(entry)` which would be the size of entry itself
// and that would simply be the size of a pointer on your system, 8 bytes,
// whereas `sizeof(*entry)` will be 44 bytes.
entry = (const void *)dataBytes;
// Any pointer type can be cased to `void *` and assigning
// a `void *` pointer so some pointer is always allowed by the compiler.
self.radius = (float)entry->radius;
self.centerPos = ccp((float)entry->xCoord, (float)entry->yCoord);
self.startAngle = (float)entry->startAngle;
self.endAngle = (float)entry->endAngle;
self.dir = entry->dir;

Converting NSStrings to C chars and calling a C function from Objective-C

I'm in an Objective-C method with various NSStrings that I want to pass to a C function. The C function requires a struct object be malloc'd so that it can be passed in - this struct contains char fields. So the struct is defined like this:
struct libannotate_baseManual {
char *la_bm_code; // The base code for this manual (pointer to malloc'd memory)
char *la_bm_effectiveRevisionId; // The currently effective revision ID (pointer to malloc'd memory or null if none effective)
char **la_bm_revisionId; // The null-terminated list of revision IDs in the library for this manual (pointer to malloc'd array of pointers to malloc'd memory)
};
This struct is then used in the following C function definition:
void libannotate_setManualLibrary(struct libannotate_baseManual **library) { ..
So that's the function I need to call from Objective-C.
So I have various NSStrings that I basically want to pass in there, to represent the chars - la_bm_code, la_bm_effectiveRevisionId, la_bm_revision. I could convert those to const chars by using [NSString UTF8String], but I need chars, not const chars.
Also I need to do suitable malloc's for these fields, though apparently I don't need to worry about freeing the memory afterwards. C is not my strong point, though I know Objective-C well.
strdup() is your friend here as that both malloc()s and strcpy()s for you in one simple step. It's memory is also released using free() and it does your const char * to char * conversion for you!
NSString *code = ..., *effectiveRevId = ..., *revId = ...;
struct libannotate_baseManual *abm = malloc(sizeof(struct libannotate_baseManual));
abm->la_bm_code = strdup([code UTF8String]);
abm->la_bm_effectiveRevisionId = strdup([effectiveRevId UTF8String]);
const unsigned numRevIds = 1;
abm->la_bm_effectiveRevisionId = malloc(sizeof(char *) * (numRevIds + 1));
abm->la_bm_effectiveRevisionId[0] = strdup([revId UTF8String]);
abm->la_bm_effectiveRevisionId[1] = NULL;
const unsigned numAbms = 1;
struct libannotate_baseManual **abms = malloc(sizeof(struct libannotate_baseManual *) * (numAbms + 1));
abms[0] = abm;
abms[1] = NULL;
libannotate_setManualLibrary(abms);
Good luck, you'll need it. It's one of the worst interfaces I've ever seen.

ios 6 and 7 doesnt return same results

It seems that our apps which use getPropertyType(..) are failing under ios7. For whatever reason, getPropertyType(..) on for example a NSString property returns NSString$'\x19\x03\x86\x13 as the type, instead of just NSString, and also instead of NSNumber it returns NSNumber\xf0\x90\xae\x04\xff\xff\xff\xff. All of this is causing some tricky problems when i later on check against a specific type. I have changed this (legacy?) code to use isKindOfClass instead, but it bothers me that I don't understand whats going on here.
The code in question:
#import <objc/runtime.h>
static const char *getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T') {
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes];
}
}
return "#";
}
What on earth is going on, why are the results different??
The buffer returned by getPropertyType isn't NULL terminated. I think it's only dumb luck that it ever worked. Also, returning the data pointed to by a newly created NSData is not guaranteed to work once that function returns.
I'd make this return an NSString.
NSString* getPropertyType(objc_property_t property) {
const char *attributes = property_getAttributes(property);
char buffer[1 + strlen(attributes)];
strcpy(buffer, attributes);
char *state = buffer, *attribute;
while ((attribute = strsep(&state, ",")) != NULL) {
if (attribute[0] == 'T') {
return [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding];
}
}
return #"#";
}
This assumes ARC.
The return value of your method need not be NULL-terminated, as it
points to the internal memory of an NSData object.
This would explain random bytes after your expected output.
Note also that the return value might not point to valid memory at all if the NSData object
is destroyed (which might be at any time after your function returns).

Xcode NSdata Garbage

I am Working on a Network application ... but before sending it over the network i am testing my packing and unpacking of data ... but i am getting a lot of garbage values
myfield in a ui text field .. my label is a uilabel ... mybutton method is called when a button is pressed
in the rec method the value(garbage) in x varies from -231231223432.... to +3423423423.....
also if i could like to pack a nsstring with this data how will i pack and unpack it
enum
{
gkMessageSent,
gkMessageNotsent
};
-(void)rec:(NSData *)data
{
const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];
switch (messageType)
{
case gkMessageSent:
{
float x = *(float *)(incomingPacket + 1 );
// value of x are not correct here
NSString *resultString = [[NSString alloc] initWithFormat:#"%f",x];
mylabel.text= resultString;
break;
}
case gkMessageNotsent:
{
mylabel.text=#"2";
break;
}
default:
mylabel.text=#"3";
break;
}
}
-(IBAction)mybutton{
float myvalue=[myfield.text floatValue];
// i check myvalue here and its fine
NSMutableData *data= [NSMutableData dataWithCapacity:1+sizeof(float)];
int myrand=1+rand()%3;
if(myrand==1)
{
char messageType = gkMessageSent;
[data appendBytes:&messageType length:1];
[data appendBytes:&myvalue length:sizeof(float)];
}
else {
char messageType = gkMessageNotsent;
[data appendBytes:&messageType length:1];
[data appendBytes:&myvalue length:sizeof(float) ];
}
[self rec:data];
}
After Some Research I found a way to pack an NSString into NSmutabledata but cant figure out the unpacking
-(IBAction)mybutton {
float myvalue=300;
NSString *resultString = [[NSString alloc] initWithFormat:#"%.2f",myvalue];
NSMutableData *data=nil;
data= [NSMutableData dataWithCapacity:1+([resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) ];
int myrand=1+rand()%3;
if(myrand==1)
{
char messageType = gkMessageSent;
[data appendBytes:&messageType length:1];
[data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
}
else {
char messageType = gkMessageNotsent;
[data appendBytes:&messageType length:1];
[data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
}
[self rec:data];
}
-(void)rec:(NSData *)data{
const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];
switch (messageType)
{
case gkMessageSent:
{
// Have to get the String here
break;
}
case gkMessageNotsent:
{
mylabel.text=#"2";
break;
}
default:
mylabel.text=#"3";
break;
}
}
You should never send "raw" data of unknown size over the network. If you were using integers, you could send the data by not sending it raw, but "correcting" its byte order to "network order" then reversing the process on the other side:
uint32t foo = htonl(myLong);
and to reverse that:
uint32t myLong = ntohl(networkData4bytesLong);
Floats and doubles can be coerced into using the above, but (to my knowledge) there is no standard way to do this. For even the following hack to work, float must be 32bit IEEE format types on both sides (probably true now on most systems).
One way is to create a union with a long and a float in it:
struct foo {
uint32_t lng;
float flt;
};
You should probably add an assert(sizeof(foo) == 4); on both sides too, just to be sure.
You put the float into a union of this type, then use htonl(foo.lng); to convert, and reverse that on the other side.
Perhaps a more reliable (but more difficult way) is to turn the float into a string, send it, then convert back to a floating point type. That said, the above should work for you with the listed assumptions (IEEE, 32bit type);
EDIT: So if you want to use a string, you can do it by appending a null terminated string to the data you send, use a "pascal" type string where the first byte is the length and a NOT null terminated string follows, or you can allow a fixed amount of space that will at least have one terminating NULL. For brevity, I am going to use the 3rd way but the "pascal" way is probably the best to use when you code it.
So, to be 100% sure we have enought space, we'll allocate 20 bytes for the float (way too much):
char floatStr[20];
sprintf(floatStr, "%f", myFloat);
[myData appendBytes:floatStr length:20];
On the other side:
unsigned char *ptr = ...; // set to the start of the string
sscanf(ptr, "%f", &myFloat);
ptr += 20;

How to store CFBitVector (or any CFType) in Core Data using CFData/NSData?

I have limited experience working with the Core Foundation types & collections, so apologies if this is obvious.
I'm using the CFBitVector type to store some bit sequences, and I need to store it in a binary data format (so that it can be added to a Core Data store). The most sensible thing seems to be to store this in a CFData type, which can be toll-free bridged with an NSData and added to the store, but I am unsure of how to do this.
Can anybody help me out with a simple example of storing CFTypes in CF/NSData?
Edit:
Is this even the right approach? Should I try converting the CFBitVector into a series of ints which can then be stored in the data model? Or perhaps a transformable attribute?
The way I ended up doing this was to roll my own attribute transformer in order to convert a CFBitVectorRef into an NSData instance. The benefit of this is that I can really cram the bit array tightly into a block of binary data, as in my case I really need to keep the storage size to a minimum.
Below is the implementation of my CFBitVectorTransformer class. It essentially reads each bit and packs them into unsigned chars ("segments" in the code below), which are then appended to a mutable NSData buffer. The code would work with types larger than unsigned chars, however I wanted the smallest chunks possible in order to really minimise the size of the resulting data.
#define kBitsPerByte 8
#implementation CFBitVectorTransformer
+ (Class)transformedValueClass
{
return [NSData class];
}
+ (BOOL)allowsReverseTransformation
{
return YES;
}
/* CFBitVectorRef -> NSData */
- (id)transformedValue:(id)value
{
if (!value) return nil;
if ([value isKindOfClass:[NSData class]]) return value;
/* Prepare the bit vector. */
CFBitVectorRef bitVector = (__bridge CFBitVectorRef)value;
CFIndex bitVectorCount = CFBitVectorGetCount(bitVector);
/* Prepare the data buffer. */
NSMutableData *bitData = [NSMutableData data];
unsigned char bitVectorSegment = 0;
NSUInteger bytesPerSegment = sizeof(char);
NSUInteger bitsPerSegment = bytesPerSegment * kBitsPerByte;
for (CFIndex bitIndex = 0; bitIndex < bitVectorCount; bitIndex++) {
/* Shift the bit into the segment the appropriate number of places. */
CFBit bit = CFBitVectorGetBitAtIndex(bitVector, bitIndex);
int segmentShift = bitIndex % bitsPerSegment;
bitVectorSegment |= bit << segmentShift;
/* If this is the last bit we can squeeze into the segment, or it's the final bit, append the segment to the data buffer. */
if (segmentShift == bitsPerSegment - 1 || bitIndex == bitVectorCount - 1) {
[bitData appendBytes:&bitVectorSegment length:bytesPerSegment];
bitVectorSegment = 0;
}
}
return [NSData dataWithData:bitData];
}
/* NSData -> CFBitVectorRef */
- (id)reverseTransformedValue:(id)value
{
if (!value) return NULL;
if (![value isKindOfClass:[NSData class]]) return NULL;
/* Prepare the data buffer. */
NSData *bitData = (NSData *)value;
char *bitVectorSegments = (char *)[bitData bytes];
NSUInteger bitDataLength = [bitData length];
/* Prepare the bit vector. */
CFIndex bitVectorCapacity = bitDataLength * kBitsPerByte;
CFMutableBitVectorRef bitVector = CFBitVectorCreateMutable(kCFAllocatorDefault, bitVectorCapacity);
CFBitVectorSetCount(bitVector, bitVectorCapacity);
for (NSUInteger byteIndex = 0; byteIndex < bitDataLength; byteIndex++) {
unsigned char bitVectorSegment = bitVectorSegments[byteIndex];
/* Store each bit of this byte in the bit vector. */
for (NSUInteger bitIndex = 0; bitIndex < kBitsPerByte; bitIndex++) {
CFBit bit = bitVectorSegment & 1 << bitIndex;
CFIndex bitVectorBitIndex = (byteIndex * kBitsPerByte) + bitIndex;
CFBitVectorSetBitAtIndex(bitVector, bitVectorBitIndex, bit);
}
}
return (__bridge_transfer id)bitVector;
}
#end
This nicely abstracts the conversion of data, allowing you to just set the CFBitVectorRef as an attribute in the data model, and should be plenty fast enough for most purposes.
I hope this helps somebody else in a similar situation.

Resources