Scanning a file with getBytes:range:? - objective-c

I'm currently scanning a binary file with the following code:
while (offset < headerLength) {
memset(buffer, 0, sizeof(buffer));
[bookData getBytes:buffer range:NSMakeRange(0 + offset, 4)];
NSString *output = [NSString stringWithCString:buffer encoding:NSUTF8StringEncoding];
if ([output isEqualToString:#"EXTH"]) {
...
}
offset++;
}
However, I suspect that's not the correct way, because it is quite slow. How to search for a specific string then?
GOOD BUT SLOW:
while (offset < headerLength) {
memset(buffer, 0, sizeof(buffer));
[bookData getBytes:buffer range:NSMakeRange(0 + offset, 4)];
if (buffer[0] == 'E' && buffer[1] == 'X' && buffer[2] == 'T' && buffer[3] == 'H') {
//run my stuff
break;
}
offset++;
}
memset(buffer, 0, sizeof(buffer));
Doesn't run my stuff
FILE * handle = fopen ([path UTF8String], "r");
while (1) {
fseek(handle, ++offset, SEEK_SET);
if (fgets(buffer, 4, handle)) {
if (buffer[0] == 'E' && buffer[1] == 'X' && buffer[2] == 'T' && buffer[3] == 'H') {
//doesn't run my stuff
break;
}
}
}
fclose(handle);

IO is slow, so I'd read in large chunks and avoid reading small chunks from a stream inside a loop. getBytes: makes a copy from the NSData object's bytes into your buffer, so you want to avoid doing that frequently too. Here is some untested pseudocode, assuming you have your NSData object to start off with:
const char *bytes = [bookData bytes];
while (offset < headerLengh - 4)
{
if (bytes[offset] == 'E' && bytes[offset + 1] == 'X' && bytes[offset + 2] == 'T' && bytes[offset + 3] == 'H')
{
//...
}
offset++;
}
I will note that there exist faster/more complicated algorithms such as boyer-moore for this type of search, but this should do for now.
I'd also advise against creating many NSString objects inside the loop. If you want to, you can create a NSString from your NSData object, and retrieve substrings inside the loop appropriately.

Instead of creating a full-fledged NSString on each iteration, you could just compare the raw bytes directly:
memset(buffer, 0, sizeof(buffer));
while (offset < headerLength) {
[bookData getBytes:buffer range:NSMakeRange(0 + offset, 4)];
if (buffer[0] == 'E' && buffer[1] == 'X' && buffer[2] == 'T' && buffer[3] == 'H') {
...
}
offset++;
}
This is assuming your buffer holds 4 chars, of course.
Also, I don't believe it's needed to clear the memory on each iteration with memset. Just once before the loop will do.

It's been a while since I practiced plain old C-style file reading, but basically, there it goes...
file handle = fopen('/var/mobile/...', 'r');
char *buf = malloc(4 * sizeof(char));
long offset = 0;
while (1) {
fseek(handle, ++offset);
ret = fgets(handle, 4, &buf); // returns NULL on EOF
if (ret) {
if (buf[0] == 'E' && ...) {
// Your logic goes here
break;
}
}
else
break;
}
fclose(handle);
Of course this is all pseudo-code, feel free to investigate or correct me.

Related

Losing double precision when dealing with timestamps

I have a simple XCTestCase:
func testExample() {
let date = "2015-09-21T20:38:54.379912Z";// as NSString;
let date1 = 1442867934.379912;
XCTAssertEqual(date1, NSDate.sam_dateFromISO8601String(date).timeIntervalSince1970);
}
This test passes, when it shouldn't, for two reasons:
1442867934.379912 becomes 1442867934.379911 in the test, even though its literally just a variable re-printed
the sam_ function (copied below) seems to think the same way, the millisecond variable becomes millisecond double 0.37991200000000003 0.37991200000000003 which when later converted from NSDate to double, seems to lose the microsecond precision (debugger):
po NSDate.sam_dateFromISO8601String(date).timeIntervalSince1970 -> 1442867934.37991
po 1442867934.379912 -> 1442867934.37991
Any idea why? The microsecond precision (6 decimal places) is really important to my application, I need to seamlessly convert to and from NSString and NSDate using the iso8601 format.
+ (NSDate *)sam_dateFromISO8601String:(NSString *)iso8601 {
// Return nil if nil is given
if (!iso8601 || [iso8601 isEqual:[NSNull null]]) {
return nil;
}
// Parse number
if ([iso8601 isKindOfClass:[NSNumber class]]) {
return [NSDate dateWithTimeIntervalSince1970:[(NSNumber *)iso8601 doubleValue]];
}
// Parse string
else if ([iso8601 isKindOfClass:[NSString class]]) {
const char *str = [iso8601 cStringUsingEncoding:NSUTF8StringEncoding];
size_t len = strlen(str);
if (len == 0) {
return nil;
}
struct tm tm;
char newStr[25] = "";
BOOL hasTimezone = NO;
// 2014-03-30T09:13:00Z
if (len == 20 && str[len - 1] == 'Z') {
strncpy(newStr, str, len - 1);
}
// 2014-03-30T09:13:00-07:00
else if (len == 25 && str[22] == ':') {
strncpy(newStr, str, 19);
hasTimezone = YES;
}
// 2014-03-30T09:13:00.000Z
else if (len == 24 && str[len - 1] == 'Z') {
strncpy(newStr, str, 19);
}
// 2014-03-30T09:13:00.000000Z
else if (len == 27 && str[len - 1] == 'Z') {
strncpy(newStr, str, 19);
}
// 2014-03-30T09:13:00.000-07:00
else if (len == 29 && str[26] == ':') {
strncpy(newStr, str, 19);
hasTimezone = YES;
}
// Poorly formatted timezone
else {
strncpy(newStr, str, len > 24 ? 24 : len);
}
// Timezone
size_t l = strlen(newStr);
if (hasTimezone) {
strncpy(newStr + l, str + len - 6, 3);
strncpy(newStr + l + 3, str + len - 2, 2);
} else {
strncpy(newStr + l, "+0000", 5);
}
// Add null terminator
newStr[sizeof(newStr) - 1] = 0;
if (strptime(newStr, "%FT%T%z", &tm) == NULL) {
return nil;
}
double millisecond = 0.0f;
NSString *subStr = [[iso8601 componentsSeparatedByString:#"."].lastObject substringToIndex:6];
millisecond = subStr.doubleValue/1000000.f;
time_t t;
t = mktime(&tm);
return [NSDate dateWithTimeIntervalSince1970:t + millisecond];
}
NSAssert1(NO, #"Failed to parse date: %#", iso8601);
return nil;
}
1442867934.379912 and 1442867934.379911 may very well equal the same number just printed differently (one rounded, the other truncated)... if microsecond time is important to you, perhaps you should look at https://developer.apple.com/library/mac/qa/qa1398/_index.html
especially because [NSDate date] can change wildly when the clock changes... and an absolute time api will not...
I ended up simply changing my API to pass double representation of a Time object. i.e. 1442867934.379912not messing with ISO8601 at all.
NSDate supports this natively. So I don't have to parse any strings. Therefore, performance is an added bonus.
A couple quirks I encountered while doing this in Rails/Rabl/Oj:
Need to send the double as a string. It seems the JSONKit on iOS doesn't like more than 15 significant digits, and neither does the JSON spec.
Rabl (initializer):
Oj.default_options = {
use_to_json: true,
second_precision: 6,
float_precision: 16
}
The default to_f was not sending the precision I needed.

`resolve_dtor() `Parentheses Algorithm

I'm running into a frustrating problem with a parentheses completion algorithm. The math library I'm using, DDMathParser, only processes trigonometric functions in radians. If one wishes to use degrees, they must call dtor(deg_value). The problem is that this adds an additional parenthesis that must be accounted for at the end.
For example, the math expression sin(cos(sin(x))) would translate to sin(dtor(cos(dtor(sin(dtor(x))) in my code. However, notice that I need two additional parentheses in order for it to be a complete math expression. Hence, the creation of resolve_dtor().
Here is my attempted solution, the idea was to have 0 signify a left-paren, 1 signify a left-paren with dtor(, and 2 signify a right-paren thus completing either 0 or 1.
- (NSMutableString *)resolve_dtor:(NSMutableString *)exp
{
NSInteger mutable_length = [exp length];
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < mutable_length; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Add right-paren for "dtor("
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
[exp insertString:#")" atIndex:index + 1];
mutable_length++;
index++;
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
return exp;
}
- (bool)check_dtor:(NSMutableString *)exp
{
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < [exp length]; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Indicate "dtor(" at index is now complete
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
// Now step back and see if all the "dtor(" expressions are complete
for (NSInteger index = 0; index < [paren_complete count]; index++) {
if ([[paren_complete objectAtIndex:index] isEqualToValue:#0] || [[paren_complete objectAtIndex:index] isEqualToValue:#1]) {
return NO;
}
}
return YES;
}
It seems the algorithm works for sin((3 + 3) + (6 - 3)) (translating to sin(dtor((3 + 3) x (6 - 3))) but not sin((3 + 3) + cos(3)) (translating to sin(dtor((3 + 3) + cos(dtor(3)).
Bottom Line
This semi-solution is most likely overcomplicated (one of my common problems, it seems), so I was wondering if there might be an easier way to do this?
Solution
Here is my solution to #j_random_hacker's pseudo code he provided:
- (NSMutableString *)resolve_dtor:(NSString *)exp
{
uint depth = 0;
NSMutableArray *stack = [[NSMutableArray alloc] init];
NSRegularExpression *regex_trig = [NSRegularExpression regularExpressionWithPattern:#"(sin|cos|tan|csc|sec|cot)" options:0 error:0];
NSRegularExpression *regex_trig2nd = [NSRegularExpression regularExpressionWithPattern:#"(asin|acos|atan|acsc|asec|acot)" options:0 error:0];
// need another regex for checking asin, etc. (because of differing index size)
NSMutableString *exp_copy = [NSMutableString stringWithString:exp];
for (NSInteger i = 0; i < [exp_copy length]; i++) {
// Check for it!
if ([exp_copy characterAtIndex:i] == '(') {
if (i >= 4) {
// check if i - 4
if ([regex_trig2nd numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 4, 4)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
else if (i >= 3) {
// check if i - 3
if ([regex_trig numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 3, 3)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
}
else if ([exp_copy characterAtIndex:i] == ')') {
depth--;
if ([stack count] > 0 && [[stack objectAtIndex:[stack count] - 1] isEqual: #(depth)]) {
[stack removeObjectAtIndex:[stack count] - 1];
[exp_copy insertString:#")" atIndex:i + 1];
}
}
}
return exp_copy;
}
It works! Let me know if there are any minor corrections that would be good to add or if there is a more efficient approach.
Haven't tried reading your code, but I would use a simple approach in which we scan forward through the input string writing out a second string as we go while maintaining a variable called depth that records the current nesting level of parentheses, as well as a stack that remembers the nesting levels that need an extra ) because we added a dtor( when we entered them:
Set depth to 0.
For each character c in the input string:
Write it to the output.
Is c a (? If so:
Was the preceding token sin, cos etc.? If so, push the current value of depth on a stack, and write out dtor(.
Increment depth.
Is c a )? If so:
Decrement depth.
Is the top of the stack equal to depth? If so, pop it and write out ).
DDMathParser natively supports using degrees for trigonometric functions and will insert the relevant dtor functions for you. It'll even automatically insert it by doing:
#"sin(42°)"
You can do this by setting the angleMeasurementMode on the relevant DDMathEvaluator object.

Checking equality of arbitrary C types using Objective-C #encode -- already exists?

I'm looking for some code to do a general purpose equality comparison of arbitrary C types as supported by Objective-C's #encode() directive. I'm essentially looking for a function like:
BOOL CTypesEqual(void* a, const char* aEnc, void* b, const char* bEnc)
Which you might call like this:
struct { ... } foo = { yadda, yadda, yadda };
struct { ... } bar = { yadda, yadda, yadda };
BOOL isEqual = CTypesEqual(&foo, #encode(typeof(foo)), &bar, #encode(typeof(bar)));
Here's what I've discovered so far:
Revelation #1
You can't do this:
BOOL CTypesEqual(void* a, const char* aEnc, void* b, const char * bEnc)
{
if (0 != strcmp(aEnc, bEnc)) // different types
return NO;
NSUInteger size = 0, align = 0;
NSGetSizeAndAlignment(aEnc, &size, &align);
if (0 != memcmp(a, b, size))
return NO;
return YES;
}
...because of garbage in the spaces between members created by alignment restrictions. For instance, the following will fail the memcmp based equality check, despite the two structs being equal for my purposes:
typedef struct {
char first;
NSUInteger second;
} FooType;
FooType a, b;
memset(&a, 0x55555555, sizeof(FooType));
memset(&b, 0xAAAAAAAA, sizeof(FooType));
a.first = 'a';
a.second = ~0;
b.first = 'a';
b.second = ~0;
Revelation #2
You can abuse NSCoder to do this, like so:
BOOL CTypesEqual(void* a, const char* aEnc, void* b, const char * bEnc)
{
if (0 != strcmp(aEnc, bEnc)) // different types
return NO;
NSMutableData* aData = [[NSMutableData alloc] init];
NSArchiver* aArchiver = [[NSArchiver alloc] initForWritingWithMutableData: aData];
[aArchiver encodeValueOfObjCType: aEnc at: a];
NSMutableData* bData = [[NSMutableData alloc] init];
NSArchiver* bArchiver = [[NSArchiver alloc] initForWritingWithMutableData: bData];
[bArchiver encodeValueOfObjCType: bEnc at: b];
return [aData isEqual: bData];
}
That's great and all, and provides the expected results, but results in who knows how many heap allocations (at least 6) and makes an operation that should be relatively cheap, very expensive.
Revelation #3
You can't use NSValue for this. As in, the following does not work:
typedef struct {
char first;
NSUInteger second;
} FooType;
FooType a, b;
memset(&a, 0x55555555, sizeof(FooType));
memset(&b, 0xAAAAAAAA, sizeof(FooType));
a.first = 'a';
a.second = 0xFFFFFFFFFFFFFFFF;
b.first = 'a';
b.second = 0xFFFFFFFFFFFFFFFF;
NSValue* aVal = [NSValue valueWithBytes: &a objCType: #encode(typeof(a))];
NSValue* bVal = [NSValue valueWithBytes: &b objCType: #encode(typeof(b))];
BOOL isEqual = [aVal isEqual: bVal];
Revelation #4
Cocotron's NSCoder implementation punts on all the hard stuff (arbitrary structs, unions, etc.), thus is no source of further inspiration.
My attempt so far
So I started in on this, docs in hand, and I roughly got this far:
BOOL CTypesEqual(void* a, const char* aEnc, void* b, const char * bEnc)
{
if (0 != strcmp(aEnc, bEnc)) // different types
return NO;
return SameEncCTypesEqual(a, b, aEnc);
}
static BOOL SameEncCTypesEqual(void* a, void* b, const char* enc)
{
switch (enc[0])
{
case 'v':
{
// Not sure this can happen, but...
return YES;
}
case 'B':
case 'c':
case 'C':
case 's':
case 'S':
case 'i':
case 'I':
case 'l':
case 'L':
case 'q':
case 'Q':
case 'f':
case 'd':
case '#':
case '#':
{
NSUInteger size = 0, align = 0;
NSGetSizeAndAlignment(enc, &size, &align);
const int result = memcmp(a, b, size);
if (result)
return NO;
break;
}
case ':':
{
if (!sel_isEqual(*(SEL*)a, *(SEL*)b))
return NO;
}
case '*':
{
if (strcmp((const char *)a, (const char *)b))
return NO;
}
case '{':
{
// Get past the name
for (const char *prev = enc - 1, *orig = enc; prev < orig || (prev[0] != '=' && prev[0] != '\0' && enc[0] != '}'); prev++, enc++);
// Chew through it
for (NSUInteger pos = 0, size = 0, align = 0; enc[0] != '}' && enc[0] != '\0'; enc++, pos += size, size = 0, align = 0)
{
NSGetSizeAndAlignment(enc, &size, &align);
// figure out where we should be w/r/t alignment
pos = align * (pos + align - 1) / align;
// Descend
BOOL sub = SameEncCTypesEqual(((uint8_t*)a) + pos, ((uint8_t*)b) + pos, enc);
if (!sub)
return NO;
}
break;
}
case '[':
{
// Skip the '['
enc++;
// Get numElements
int numElements = 0;
sscanf(enc, "%d", &numElements);
// Advance past the number
for (; enc[0] <= '9' && enc[0] >= '0'; enc++);
// Get the size
NSUInteger size = 0, align = 0;
const char * const elementType = enc;
NSGetSizeAndAlignment(elementType, &size, &align);
for (NSUInteger i = 0; i < numElements; i++)
{
BOOL elementEqual = SameEncCTypesEqual(((uint8_t*)a) + i * size, ((uint8_t*)b) + i * size, elementType);
if (!elementEqual)
return NO;
}
break;
}
case '(':
{
NSLog(#"unions?! seriously, bro?");
return NO;
break;
}
default:
{
NSLog(#"Unknown type: %s", enc);
return NO;
break;
}
}
return YES;
}
...and about when I got to unions, I said to myself, "Self, why are you doing this? This is exactly the sort of code with a million little corner cases to miss, and really, it seems like something that should have been written a bunch of times already, by other people with way more patience." So here I am. Anyone know of a tried-and-true implementation of this in the (public) frameworks or "in the wild" that doesn't come with all the extra weight of using NSCoder?
Why not just make a function that skips the padding?
First, you would need to guess the padding policy. That's the easy part.
Then you use the encoding information provided by #encode to map the data types to masks, and use those masks to compare.
A trivial example:
struct m { char a; int b; };
struct n { char c; struct m d; int e; };
Could be transformed into (lets assume sizeof(int) is 4):
struct_m_mask = { 1, 4, 0 };
struct_n_mask = { 1, 1, 4, 4, 0 };
Optimization of the representation is of course possible in the case the alignment allows, e.g.:
struct_b_mask = { 2, 4, 4, 0 };
Then, you could walk this array to do the comparisons. A[n+1] - A[n] gives the hole size, if there's no hole ahead, like in the case of (b, e), then you can merge them.
That's the simplest way I could come up with. Probably you can implement more complex tricks.
BTW, my guess is that given the stuff is constant, the compiler could compute the masks at compile-time, but perhaps that's too much asking...
Regarding the padding issue you may have to make something like a function for each struct that turns it into an array for comparison or returns a single value at an index. It isn't very optimal but that is usually why sorting algorithms let you pass in function pointers that do the actual comparison.

unable to detect application running with another user (via switch user)

Use case: I login as "user1" and launch Safari, then I click "user1" on top-right corner and switch user to "user2".
Now, I am trying to detect whether Safari is running for "user1" but I am unable to do so with standard calls. I am using OS X 10.8 Mountain Lion for both development and running my code.
I have used the following but in vain:
[[NSWorkspace sharedWorkspace] runningApplications] - Safari not there in the list
GetNextProcess() - Safari does not come up
GetProcessForPID() - I get an error "no such process"
But when I do a ps -aef | grep Safari from the terminal, I can see Safari. (This is not only the case with Safari but other applications as well.)
Can someone please help. Thank you very much.
You can use sysctl or ps command to get a list of all BSD processes.Have a look at Technical Q&A QA1123
#include <sys/sysctl.h>
#include <pwd.h>
typedef struct kinfo_proc kinfo_proc;
static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
int err;
kinfo_proc * result;
bool done;
static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;
// assert( procList != NULL);
// assert(*procList == NULL);
// assert(procCount != NULL);
*procCount = 0;
// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we're done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.
result = NULL;
done = false;
do {
assert(result == NULL);
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0) {
result = malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
if (err == 0) {
done = true;
} else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && ! done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
if (err == 0) {
*procCount = length / sizeof(kinfo_proc);
}
assert( (err == 0) == (*procList != NULL) );
return err;
}
+ (NSArray*)getBSDProcessList
{
kinfo_proc *mylist =NULL;
size_t mycount = 0;
GetBSDProcessList(&mylist, &mycount);
NSMutableArray *processes = [NSMutableArray arrayWithCapacity:(int)mycount];
for (int i = 0; i < mycount; i++) {
struct kinfo_proc *currentProcess = &mylist[i];
struct passwd *user = getpwuid(currentProcess->kp_eproc.e_ucred.cr_uid);
NSMutableDictionary *entry = [NSMutableDictionary dictionaryWithCapacity:4];
NSNumber *processID = [NSNumber numberWithInt:currentProcess->kp_proc.p_pid];
NSString *processName = [NSString stringWithFormat: #"%s",currentProcess->kp_proc.p_comm];
if (processID)[entry setObject:processID forKey:#"processID"];
if (processName)[entry setObject:processName forKey:#"processName"];
if (user){
NSNumber *userID = [NSNumber numberWithUnsignedInt:currentProcess->kp_eproc.e_ucred.cr_uid];
NSString *userName = [NSString stringWithFormat: #"%s",user->pw_name];
if (userID)[entry setObject:userID forKey:#"userID"];
if (userName)[entry setObject:userName forKey:#"userName"];
}
[processes addObject:[NSDictionary dictionaryWithDictionary:entry]];
}
free(mylist);
return [NSArray arrayWithArray:processes];
}

malloc error when reading file in iOS

i have this function that reads a line from a file character by character and inserts it into a NSString.
RANDOMNLY the system crashes with this error:
malloc: *** error for object 0x1e1f6a00: incorrect checksum for freed
object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
function:
NSDictionary *readLineAsNSString(FILE *f,int pospass,
BOOL testata, int dimensioneriga)
{
char *strRet = (char *)malloc(BUFSIZ);
int size = BUFSIZ;
BOOL finito=NO;
int pos = 0;
int c;
fseek(f,pospass,SEEK_SET);
do{ // read one line
c = fgetc(f);
//Array expansion
if (pos >= size-1) {
size=size+BUFSIZ;
strRet = (char *)realloc(strRet, size);
}
if(c != EOF) {
strRet[pos] = c;
pos=pos+1;
}
if(c == EOF) {
finito=YES;
}
} while(c != EOF && c != '\n');
if (pos!=0) {
for (int i = pos; i<=strlen(strRet)-1; i++) //size al posto di pos
{
strRet[i] = ' ';
}
}
NSString *stringa;
if (pos!=0) {
stringa=[NSString stringWithCString:strRet encoding:NSASCIIStringEncoding];
} else {
stringa=#"";
}
long long sizerecord;
if (pos!=0) {
sizerecord= (long long) [[NSString stringWithFormat:#"%ld",sizeof(char)*(pos)] longLongValue];
} else {
sizerecord=0;
}
pos = pospass + pos;
NSDictionary *risultatoc = #{st_risultatofunzione: stringa,
st_criterio: [NSString stringWithFormat:#"%d",pos],
st_finito: [NSNumber numberWithBool:finito],
st_size: [NSNumber numberWithLongLong: sizerecord]
};
//free
free(strRet);
return risultatoc;
}
where "finito" is a flag, "pos" is the position in the file line,"pospass" is the position in the entire file, "c" is the character, "strRet" is the line and BUFSIZ is 1024.
Each file has n line with the same lenght (for file).
Thanks!!!
This part:
if (pos!=0) {
for (int i = pos; i<=strlen(strRet)-1; i++) //size al posto di pos
{
strRet[i] = ' ';
}
}
is broken. strlen just reads until it finds a \0 ... since you didn't put one in, it can just keep reading off the end of your buffer.
You already have size, so just use that, or better still just terminate strRet instead of right-filling with spaces:
strRet[pos] = '\0';