Redefinition of 'struct __block_literal_1' in Obj-C - objective-c

I've been working around this problem for a while now and it's really driving me insane. Whenever I declare a block, I get a compile error in Xcode 4.1 compiling with LLVM GCC 4.2:
Redefinition of 'struct __block_literal_1'
Even examples of blocks copy-pasted from the documentation throw the error:
int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
return num * multiplier;
};
I've had several attempts to find a solution to this error to no avail. Any help would be appreciated.
Update:
I know it's been a while since I posted, but I will need to tackle this problem sooner or later. I think this has something to do with using static libraries. When a static library with blocks are added to a project, the error is thrown. Will post more details soon.

Related

why does not address of non-exist extern variable equal to null

I found something very confusing about non-exists extern variable.
As the code below, obviously, compiler will generate an error cause there is not a int variable named iiii.
But, if the line code of "NSLog(#"%p", &iiii);" is deleted, no error will be generated. And the "not null" will be printed if I execute the output binary.
Why is this happen? I am hoping to get an error, no matter how I manipulate iiii.
Thanks for your help
IDE: Xcode 10.3 with clang
Target platform: iOS simulator 12.4
extern int iiii;
if(NULL != (&iiii)) {
NSLog(#"not null");
}
NSLog(#"%p", &iiii);
Building an application includes the distinct stages of compilation and linking.
It is the linking stage, which occurs after compilation, that global declarations and "extern" references to such declarations and linked together. If you look at the error you get when the NSLog() is in your code you will see it is a linker (coming from ld, the linker/loader) error.
During compilation the compiler assumes that any extern references will be resolved by the linker. So it assumes the iiii variable will exist, and as such it will have an address so it can optimise away the test.
The above assumes strong linking, when a compiler is informed that weak linking will be used then it cannot make the assumption that an external reference will be non-null. E.g. if the variable iiii was declared in a library/framework which was weakly dynamically linked to your application then the compiler could not assume the variable existed and the application would need to test somewhere that the weakly-linked dynamic library was present. However we're getting into another topic entirely... (ask a new question if you have a dynamic linking issue).
HTH

Why does the C compiler not warn about malloc size errors?

I made a member struct that I assigned in the ViewDidLoad of my iOS app. I used malloc to allocate space for this struct that was then used throughout my class. Like this:
self.myData = malloc(sizeof(MyData));
Except what I really did was this:
self.myData = malloc(sizeof(MyOtherStruct));
I accidentally set sizeof() in the malloc call to be a different struct (that isn't the same size). I didn't notice this mistake for a very long time because the app only rarely crashed. An update to the OS caused the crash to happen more frequently.
My question is, why can compiler's not warn about this sort of thing? Is it something compiler's don't know about or is it a design choice to allow users's to malloc whatever size they please?
"How can I find this error faster?"
There are a bunch of ways to find the error faster.
Solution #1
The static analyzer cathes this error. Press command-shift-B in Xcode. For example, take the following code:
#include <stdlib.h>
struct x { double x; };
struct y { char y; };
int main(int argc, char **argv) {
struct x *p = malloc(sizeof(struct y));
p->x = 1.0;
return 0;
}
Running the analyzer produces this error for me:
Result of 'malloc' is converted to a pointer of type 'struct x' which is incompatible with sizeof operand type 'struct y'
Solution #2
It is recommended to write the code this way instead:
self.myData = malloc(sizeof(*self.myData));
Just do it this way in the future. This is not only less error-prone, but it is easier to remember.
Solution #3
Use a language like Swift or C++ where the language's type system help you avoid this kind of error. C is less forgiving in many ways. It was invented in the early 1970s, you just kind of have to accept that if you want to use it, and these kinds of errors are a major part of the reason why C++ and Swift even exist in the first place.
Solution #4
Use a run-time memory bounds checker, like the address sanitizer. This will detect the error when memory is accessed, not when it is allocated, but it will still give you stack traces for both access and allocation (and free, if the memory has been freed). Anyone writing C these days should familiarize themselves with the address sanitizer and its friends, tsan, ubsan, etc.
Valgrind also achieves the same effect but the address sanitizer has a better user experience for common use cases.
Question as asked
The compiler only really gives you errors and warnings for type errors. This isn't a type error, it's a runtime error. There are a few "likely" runtime errors that the compiler can detect, but they are very few in number. Things like forgetting to use the return value of malloc()... e.g.,
void f(void) {
malloc(1); // warning
}
The compiler isn't much better than that.
Again, this is the impetus for newer languages like C++ and Swift, which have type systems which allow you to generate errors when you allocate things incorrectly, and this is also the impetus for static analysis (which is a tough problem).
That happens because is not ARC responsability to deal with malloc() and even free()
The ARC just handle with objects allocated like [Object alloc]
In your case, when you do self.myData = malloc(sizeof(MyOtherStruct));, that can be interpreted for example with something like this:
self.myData = malloc(N*sizeof(MyData));
//what can represents self.myData[0]..self.myData[N-1]
For the last, remember when you use sizeof(), it will tell you about the size of the type, that you are passing as a paramter, calculated in compile-time.
You can check this link for more information about object allocation
And also check Apple Documentation about Memory Alloc

Why doesn't the Xcode compiler auto-error for pointer type safety?

For example:
void modLongerAddress(double *aPtr) {
*aPtr = 1.11;
// or some number that goes beyond the storage capacity of a single precision float
}
int main(int argc, const char * argv[]) {
float singlePrecision = 1.11;
modLongerAddress(&singlePrecision);
return 0;
}
As far as I can tell, this only generates a warning. Wouldn't this situation be considered dangerous enough to generate a hard error, or am I missing something?
Thanks to WhozCraig's help, I found the setting that was causing this. Appears that in XCode 6.2 (6C101), there is a setting called "Treat incompatible Pointer Type Warnings as Errors" that is set to "No" by default.
This setting is found in the Build Settings of the Project, under "Apple LLVM 6.0 - Warnings - All languages".
Simply toggling to "Yes" did the trick, and the build failed as originally expected.
EDIT: It would be a big bonus I suppose if someone could explain why this would be set to "No" by default? It appears this may not be true for all versions of Xcode?

Objective C : can't operate download issue

i'm new to Xcode objective-c and I have a task to make a newsletter that downloadable.
So, I got some source code and tweak a bit but I got some error that said
"Implicit conversion loses integer precision : 'long' to 'int'
here are my code
-(void)downloadIssue:(IssueInfo*)issueInfo{
NewsstandDownloader* downloader = [[AppDelegate instance] newsstandDownloader];
downloader.delegate = self;
long index = [self.publisher indexOfIssue:issueInfo];
[downloader downloadIssue:issueInfo forIndexTag:index]; <-- Error
}
Please help me.
Thank you.
That's just a compiler warning and a mild one at that. If you were dealing with a document that had more than, say, 32000 pages then you might need to be concerned about it.
The way to solve the problem is to either change the declaration of the function you're calling to something like:
[downloader downloadIssue:(IssueInfo *)issueInfo forIndexTag:(long)index]
or, simply use a cast:
int index = (int)[self.publisher indexOfIssue:issueInfo];
"int" isn't usually a good thing to use in Objective C as there are different lengths and capacities to it on different platforms (32 bit versus 64 bit, iOS vs MacOS, etc.). It's better to use something more Objective-C specific, like NSInteger or NSUInteger.

PyObjC: how to delete existing Objective-C class

I created a ObjC class earlier. How can I delete it again? Because at some later point, I want to recreate it by another version.
Right now, if I just redeclare it, I get the exception X is overriding existing Objective-C class.
I don't know how to do this in PyObjC, but the Objective-C runtime function for doing this should be objc_disposeClassPair(). Searching around a bit yielded an indication that using this Objective-C runtime feature might not work in PyObjC:
A PyObjC SVN commit message from January 2008 reads: Initial attempt of using objc_disposeClassPair. Disabled because this causes an unexpected crash. http://blog.gmane.org/gmane.comp.python.pyobjc.cvs/month=20080101
The code in question is still in the current class-builder.m of PyObjC's source in line 164ff and is prefixed with an interesting comment:
/*
* Call this when the python half of the class could not be created.
*
* Due to technical restrictions it is not allowed to unbuild a class that
* is already registered with the Objective-C runtime.
*/
int
PyObjCClass_UnbuildClass(Class objc_class __attribute__((__unused__)))
{
PyObjC_Assert(objc_class != nil, -1);
PyObjC_Assert(objc_lookUpClass(class_getName(objc_class)) == nil, -1);
//objc_disposeClassPair(objc_class);
return 0;
}
That being said, I never used this in Objective-C itself and I don't know much about PyObjC. Hope this helps.