Cocoa multiple threads, locks don't work - cocoa

I have a threadMethod which shows in console robotMotorsStatus every 0.5 sec. But when I try to change robotMotorsStatus in changeRobotStatus method I receive an exception. Where I need to put the locks in that program.
#import "AppController.h"
#implementation AppController
extern char *robotMotorsStatus;
- (IBAction)runThread:(id)sender
{
[self performSelectorInBackground:#selector(threadMethod) withObject:nil];
}
- (void)threadMethod
{
char string_to_send[]="QFF001100\r"; //String prepared to the port sending (first inintialization)
string_to_send[7] = robotMotorsStatus[0];
string_to_send[8] = robotMotorsStatus[1];
while(1){
[theLock lock];
usleep(500000);
NSLog (#"Robot status %s", robotMotorsStatus);
[theLock unlock];
}
}
- (IBAction)changeRobotStatus:(id)sender
{
robotMotorsStatus[0]='1';
}

extern char *robotMotorsStatus;
You have not, in any code that you've shown, set this pointer to point anywhere. (Are you using an SDK for some robotics package that will initialize this variable for you? If so, can you show the configuration setting that tells it that this is the variable to initialize?)
string_to_send[7] = robotMotorsStatus[0];
string_to_send[8] = robotMotorsStatus[1];
If that robotMotorsStatus has not been initialized by an SDK or by code not shown, then these are accessing memory at a random address. It would not surprise me if this were crashing you, and if this were the “exception” you referred to but did not name.
robotMotorsStatus[0]='1';
Same potential problem here.
NSLog (#"Robot status %s", robotMotorsStatus);
This assumes that robotMotorsStatus contains at least one character, and that the last one is a zero byte (the null character)—i.e., that robotMotorsStatus points to a C string. As I've already noted, you have not shown that robotMotorsStatus points to anything definite, and even if it does point somewhere, you have not shown that the contents of that memory are a C string.
If there isn't a null character within the actual bounds of the array, then the array does not contain a C string, and attempting to read the whole C string, as passing the array to a %s formatter does, will cause a crash after you go past the end of the array. If the other two accesses of robotMotorsStatus are not your crash, this one may be.
The solution here is to not only have the pointer variable point somewhere you've intended, but to have a valid C string—including the null character—completely within that space.
Incidentally, these problems have nothing to do with threads.

Related

passing pointers

I have this declared above:
char PandaImage[] = "images/panda.png";
SDL_Texture* PandaTexture = nullptr;
I have a function to create textures:
void LoadMedia( SDL_Texture *ThisTexture, char *Image )
{
SDL_Surface* TempSurface = nullptr;
.......................
ThisTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
I call it as:
LoadMedia( PandaTexture, PandaImage );
It builds, logs the image loaded and texture created, but no image
If I hard change the line ( use Panda directly instead of This ):
PandaTexture = SDL_CreateTextureFromSurface( gRenderer, TempSurface );
My image is there.
I have always had trouble with & * and passing.
Is there a good, simple help for me?
Thanks for your kind help - back to Google for now
In short, I think you could solve your problem by changing the function to:
void LoadMedia( SDL_Texture** thisTexture, char* Image)
{
...
(*thisTexture) = SDL_CreateTextureFromSurface( gRenderer, TempSurface);
}
And by calling the function using:
LoadMedia( &PandaTexture, PandaImage);
An explanation:
Variables and Pointers
A variable is used to store data (a primitive or a class instance). For example:
int a = 10;
stores an integer in memory. This means, that symbol 'a' now represents number 10, which is stored somewhere in your computer's memory as 4 bytes.
A pointer is used to store an address (this address points towards a variable). For example:
int* a_address = 1234;
says that there is an integer stored at address 1234 in your computer's memory. A pointer always takes up the same amount of space (4 bytes on a 32 bit machine and 8 bytes on a 64 bit machine), as it simply stores an address.
Getting the Address of a Variable [&]
You will rarely ever set the address of a pointer yourself. Often, pointers are the result of a "new" call. Using "new" reserves memory to store an instance of the class you want to create, and returns the address of the object. In essence, it says: "I created an object for you, and you can find it at this location in your memory".
Alternatively, when you have a normal variable (primitive of class instance), you can find its address by using the & character. For example:
int a = 10;
int* a_address = &a;
says: "store the location of variable a in pointer a_address. Why would you do this? Say you have a very large instance (for example an SDL_Texture consisting of many, many pixels) and you want to pass it to a function (or pass it back outside of the function). If you were to pass it to the function as SDL_Texture thisTexture, you are copying the entire object (a so-called pass by value). This is time consuming. Alternatively, you could simply pass the address to the function, as an SDL_Texture * thisTexture. This is a so called pass by reference, and it is much faster as you can imagine.
Getting the Variable at an Address [*]
Obviously, if you have an address, you also need a way to get the actual variable at that address. This is done using the * character. It is called "dereferencing". For example:
int a = 10;
int* a_address = &a;
int b = (*a_address);
This last line says: "Give me the variable, stored at address a_address, and put it in b".
Function Parameters Going Out-of-scope
When a function ends, its local variables (including parameters) go out-of-scope. This means that their memory is freed (for variables, not for dynamically allocated objects stored as pointers!). Their values will be forgotten. In your case, you are passing an SDL_Texture * as a parameter. This means, a copy is made of the address stored in PandaTexture. This address is copied over to thisTexture. You then write the return value of SDL_CreateTextureFromSurface to thisTexture. Next the function ends, and thisTexture goes out-of-scope. As a result, the location of your SDL_Texture (the SDL_Texture * pointer) is lost forever. You actually want to store the address to pointer PandaTexture, but as you can see, the address is only written to thisTexture.
Solution: How to Fix your Function
We can fix this by passing a pointer, to your pointer called PandaTexture. A "pointer to a pointer" is written as:
SDL_Surface** thisTexture;
We want to pass the address of pointer PandaTexture to this. This way, we can write to PandaTexture from inside your method! After all, we know where PandaTexture stores its pointer in memory, allowing us to change it. To actually put the address of PandaTexture in it, we need to use the & character in the function call as such:
LoadMedia(&PandaTexture, PandaImage);
Next, inside of our function, we want to change the value of PandaTexture. However, we were passed &PandaTexture and not PandaTexture itself. To write the value of &PandaTexture (the address where our texture will be stored), we need dereferencing, as such:
(*thisTexture) = SDL_CreateTextureFromSurface(gRenderer, TempSurface);
This works because: "thisTexture is a pointer to a pointer to an SDL_Texture (aka an SDL_Texture**). By dereferencing it, we obtain a pointer to an SDL_Texture (aka an SDL_Texture*). Here we can store the return value of the SDL_CreateTextureFromSurface function.
Why do we not run into out-of-scope issues here? Parameter thisTexture will still go out of scope, and its value will be forgotten. But! We didn't write to thisTexture, instead we wrote our SDL_Texture * pointer to the address that thisTexture points to! This bit of memory is not cleared due to scoping, so we can view the results from outside the function!
In summary, you can solve your problem using a pointer to a pointer. I hope the above clears up the concepts of pointers, variables, addresses and dereferencing a bit!

C++(Visual Studio 2012): Copying a function's parameter char* to a dynamically allocated one

I have this structure defined and a class in my project. It is a class that holds id numbers generated by GetIdUsingThisString(char *), which is a function that loads a texture file into GPU and returns an id(OpenGL).
The problem is, when I try to read a specific file, the program crashes. When I run this program in VS with debugging it works fine, but running .exe crashes the program(or running without debugging from MSVS). By using just-n-time debugger I have found out that, for num of that specific file, Master[num].name actually contains "\x5" added(concatenation) at the end of the file path, and this is only generated for this one file. Nothing out of this method could do it, and I also use this type of slash / in paths, not \ .
struct WIndex{
char* name;
int id;
};
class Test_Class
{
public:
Test_Class(void);
int AddTex(char* path);
struct WIndex* Master;
TextureClass* tex;
//some other stuff...
};
Constructor:
Test_Class::Test_Class(void)
{
num=0;
Master=(WIndex*)malloc(1*sizeof(WIndex));
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");
Master[0].id=GetIdUsingThisString(Master[0].name);
}
Adding a new texture:(The bug)
int Test_Class::AddTex(char* path)
{
num++;
Master=(WIndex*)realloc(Master,(num+1)*sizeof(WIndex));
Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
strcpy(Master[num].name,path);<---HERE
Master[num].id=GetIdUsingThisString(path);
return Master[num].id;
}
At runtime, calling AddTex with this file would have path with the right value, while Master[num].name will show this modified value after strcpy(added "\x5").
Question:
Is there something wrong with copying(strcpy) to a dynamically allocated string? If i use char name[255] as a part of the WIndex structure, everything works fine.
More info:
This exact file is called "flat blanc.tga". If I put it in a folder where I intended it to be, fread in GetIdUsingThisString throws corrupted heap errors. If I put it in a different folder it is ok. If I change it's name to anything else, it's ok again. If I put a different file and give it that same name, it is ok too(!!!). I need the program to be bug free of this kind of things because I won't know which textures will be loaded(if I knew I could simply replace them).
Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
Should be
Master[num].name=(char*)malloc( (strlen(path)+1) * sizeof(char));
There was not place for the terminating NULL character
From http://www.cplusplus.com/reference/cstring/strcpy/:
Copies the C string pointed by source into the array pointed by
destination, including the terminating null character (and
stopping at that point).
The same happens here:
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");
Based on the definitions (below) - you should use strlen(string)+1 for malloc.
A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).
The strcpy() function shall copy the string pointed to by s2 (including the terminating null byte)
Also see discussions in How to allocate the array before calling strcpy?

Enumerate BOOLs from an NSDictionary

I have a .plist file that is loaded into my Xcode project. I have successfully put it in the documents directory of my iPhone while testing it. When I dump the contents into an NSMutableDictionary, and try to enumerate it, I get EXC_BAD_ACCESS crashes. They keys all have BOOLs associated as their values. What am I doing wrong?
My code now:
for (id key in achDict) {
NSLog(#"Achievement:%# done:%#", key, [[achDict objectForKey:key] boolValue]);
}
This always returns EXC_BAD_ACCESS in a crash.
Your NSLog is expecting two objects but you are passing it a string 'key' and an Integer. A Bool Value is not an Object, it returns an Integer value (0 for False and 1 for True). %# is for Objective C Objects. Instead use %d to get Integer Values such as C Booleans.
Change your NSLog statement to:
NSLog(#"Achievement:%# done:%d", key, [[achDict objectForKey:key] boolValue]);
Apple's String Programming Guide has a useful section on String Modifiers

Boolean as a property in Cocoa

I'm sure that this has been asked MANY times before, but it's still giving me trouble. I define my class's Boolean property like this:
#property(readwrite,assign) BOOL namesVisible;
And it doesn't give compiler errors, but it NSLogs as (null). Obviously I'm doing something wrong here, but I'm at a loss to what it is.
BOOLs are just chars, either 0 or 1. As such, you don't need to use a storage keyword in the property declaration, so it should be:
#property (readwrite) BOOL namesVisible;
Second, when logging a BOOL, use the int format string, %d, or pass in a string:
NSLog(#"My Boolean: %d, or %#", object.namesVisible, object.namesVisible ? #"Yes" : #"No");
Because you're trying to log it as an object by using %#, and a BOOL isn't an object, and your property's value is NO and you're lucky.
The last part is because you're only passing a BOOL to NSLog, but since your format string says to expect an object pointer, it will read a pointer's worth from the argument stack. Since a pointer is bigger than a BOOL, it's reading more than you passed it. You're lucky that it got zeroes for all four/eight bytes (your NO was only one of them); the result is that it sent its description message to nil, which returned nil for the description string, which prints as “(null)” in the output.
If you'd been unlucky and/or the property's value had been YES, it would have read something that isn't nil, but is nonetheless probably not a pointer to an object that exists. As such, trying to log that would cause a crash, probably of the EXC_BAD_ACCESS variety. If you'd been unlucky and lucky at the same time, you would have printed the description of an actual object, and wondered how the hell your BOOL looked like that.
The solution is one of two things:
NSLog(#"My Boolean property: %d", (int)[myObject myBooleanProperty]);
or:
NSLog(#"My Boolean property: %#", [myObject myBooleanProperty] ? #"YES" : #"NO");
The former casts the Boolean value to a full-size int and prints that value as such (most probably either 0 or 1), whereas the latter will pass either #"YES" or #"NO" as the argument depending on the Boolean value. Since NSString literals are (NSString) objects, the %# formatter becomes the right one.

Convert NSData to NSString

I am receiving a successful connection to the server and i am in my callback function:
I am trying to get the name of the host and print that to my console:
if(theType == kCFSocketConnectCallBack){
NSLog(#"Connection is accepted");
CFSocketNativeHandle nativeSocket = CFSocketGetNative(theSocket);
uint8_t name[SOCK_MAXADDRLEN];
socklen_t namelen = sizeof(name);
NSData *peer = nil;
if (getpeername(nativeSocket, (struct sockaddr *)name, &namelen) == 0) {
peer = [NSData dataWithBytes:name length:namelen];
NSString *string = [[NSString alloc] initWithData:peer encoding:NSUTF8StringEncoding];
NSLog(#"IP adress of connected peer: %#", string);
}
When i run the application in the debug mode i can see the IP address value assigned to name , so it's successful in getting the name , each value is uint8_t..
The peer length is showing me 16;
My problem converting it to NSData then NSString...
output:
2010-01-31 13:57:58.671 IP adress of connected peer: (null)
My string is being output as NULL,
Any advise is appreciated, thanks....
getpeername() doesn't return the host name of the remote side; it returns the address:
$ man getpeername
...
DESCRIPTION
The getpeername() function returns the address of the peer connected to
the specified socket.
You want getnameinfo():
$ man getnameinfo
...
DESCRIPTION
The getnameinfo() function is used to convert a sockaddr structure to a
pair of host name and service strings. It is a replacement for and pro-
vides more flexibility than the gethostbyaddr(3) and getservbyport(3)
functions and is the converse of the getaddrinfo(3) function.
or gethostbyaddr():
$ man gethostbyaddr
...
DESCRIPTION
The getaddrinfo(3) and getnameinfo(3) functions are preferred over the
gethostbyname(), gethostbyname2(), and gethostbyaddr() functions.
The gethostbyname(), gethostbyname2() and gethostbyaddr() functions each
return a pointer to an object with the following structure describing an
internet host referenced by name or by address, respectively.
sockaddr is a struct, not just a typedef for a character array. You need to pass getpeername the address to an actual sockaddr struct, and then build the string from the sa_data field of that struct--and that's assuming that sa_data is actually a string for your address type, which the documentation doesn't suggest you can actually count on. As another answer says, this is not the call you want if your goal is to get a string representation to print out.
(Also, you don't need an NSData at all to go from a character array to an NSString; you can just use -[NSString initWithBytes:length:encoding:])
First, check to make sure that peer contains an instance of NSData that is non-zero in length.
If it does, then the most likely problem is that the data is not properly of the specified encoding causing NSString to fail the encoding and return a nil string. If it is an encoding issue, there is API on NSString for doing lossy encodings. Even if lossy isn't acceptable in your final solution, going that route can be quite helpful to figuring out what is going wrong.
That assumes by NULL you really mean nil. It would be helpful to paste the exact output of the log line.

Resources