implicit conversion of 'bool' (aka 'signed char') to 'nsdata *' is disallowed with arc - automatic-ref-counting

When perform a migration of my project to Obejctive-C ARC, i got one error:
implicit conversion of 'bool' (aka 'signed char') to 'nsdata *' is disallowed with arc
The function Xcode is referring to for this error is returning NO or nil although its returning type is of type NSData:
- (NSData *)compressBytes:(Bytef *)bytes length:(NSUInteger)length error:(NSError **)err shouldFinish:(BOOL)shouldFinish
{
if (length == 0) return nil;
int status;
if (status == myVariable) {
break;
} else if (status != y_OK) {
if (err) {
*err = [[self class] deflateErrorWithCode:status];
}
return NO;
}
However, i am not quite sure i know how to fix that, any idea will be appreciated.

Under ARC you are only allowed to return an object or nil. Period.
This is because ARC not just requires, but DEMANDS that you don't do anything fishy with pointers - that pointers either point to objects or nil.
ARC is having fits because you are trying to stuff NO (a zero value) into a pointer. This violates the rules and that is why you are getting an error.
We can't help you fix it because a) we don't know what the valid return values are for (why NO? Why not nil?). Since this appears to be a code fragment, it is hard to help you. Sorry.

Just don't do that. NO is not in any sense a valid return value for that function. Your code was broken before ARC, and now it's still broken after.
Also, these lines:
int status;
if (status == myVariable) {
break;
}
are exactly the same as these:
if (myVariable == nil) {
break;
}
except written in a really confusing way, and relying on ARC to initialize status. I'm pretty sure that's not what you wanted.
Basically, this method looks completely wrong.

Related

Derefencing nullptr warning in c++

if (nullptr!=timing_info)
{
timing_info->h = start_time;
}
I get the following warning
autosar_cpp14 a5-1-1 violation
Using literal "NULL" other than type initialization, where symbolic names shall be used instead.
The autosar rule a5-1-1 reads
Rule A5-1-1 (required, implementation, partially automated) Literal
values shall not be used apart from type initialization, otherwise
symbolic names shall be used instead.
I never thought "nullptr" was a literal value. If it is a literal value, then what is the best way to handle this warning.
As you've already quoted, Rule A5-1-1 says
Rule A5-1-1 (required, implementation, partially automated)Literal
values shall not be used apart from type initialization,
otherwise symbolic names shall be used instead.
(source)
The idea behind this rule is that you should not use magic constants, i.e., don't write something like
// 100 is a magic constant. It's not clear what the next line means without comments.
if (list.size() > 100) {
std::cout << "error!";
} else {
std::cout << "everything ok!";
}
but rather, write
static constexpr auto maximum_allowed_size = 100;
// The next line speaks for itself: "if list is bigger than allowed ..."
if (list.size() > maximum_allowed_size) {
std::cout << "error!";
} else {
std::cout << "everything ok!";
}
This extra constant increases readability in most cases.
Since nullptr is a literal and you use that literal nullptr for something else than "type initialization", your code violates that rule A5-1-1.
I don't know if autosar intentionally discourages the use of literal nullptr, I personally don't see a reason why one should do this. Maybe it has been overseen (should be an exception).
You can rephrase your code to silence the checker:
if (timing_info) // implicitly convert pointer to bool
as that variant apparently makes the checker unhappy, too, here is another variant:
if (!!timing_info) // convert pointer to bool using double negation
You could also use casts, but I wouldn't do that. Frankly speaking, I like the original variant (if (nullptr != timing_info)) most.

Why is this code correct while it should clearly run into an infinite loop?

I have been having a problem with this code for a while. The placement of recursive call of the function does not seem right.
i tried running the code and yes it does run into a infinite loop.
// I DEFINE HEAP STRUCTURE AS :
struct heap_array
{
int *array; // heap implementation using arrays(note : heap is atype of a tree).
int capacity; // how much the heap can hold.
int size; //how much size is currently occupied.
void MaxHeapify(struct heap_array *h,int loc) // note : loc is the location of element to be PERCOLATED DOWN.
{
int left,right,max_loc=loc;
left=left_loc_child(h,loc);
right=right_loc_child(h,loc);
if(left !=-1 && h->array[left]>h->array[loc])
{
max_loc=left;
}
if(right!=-1 && h->array[right]>h->array[max_loc])
{
max_loc=right;
}
if(max_loc!=loc) //i.e. if changes were made:
{
//swap the element at max_loc and loc
int temp=h->array[max_loc];
h->array[max_loc]=h->array[loc];
h->array[loc]=temp;
}
MaxHeapify(h,max_loc); // <-- i feel that this recursive call is misplaced. I have seen the exact same code in almost all the online videos and some books i referred to. ALSO I THINK THAT THE CALL SHOULD BE MADE WITHIN THE SCOPE OF condition if(max_loc!=loc).
//if no changes made, end the func right there.
}
In your current implementation, it looks like you don't have a base case for recursion to stop.
Remember that you need a base case in a recursive function (in this case, your MaxHeapify function), and it doesn't look like there is one.
Here is an example of MaxHeap which may be resourceful to look at
// A recursive function to max heapify the given
// subtree. This function assumes that the left and
// right subtrees are already heapified, we only need
// to fix the root.
private void maxHeapify(int pos)
{
if (isLeaf(pos))
return;
if (Heap[pos] < Heap[leftChild(pos)] ||
Heap[pos] < Heap[rightChild(pos)]) {
if (Heap[leftChild(pos)] > Heap[rightChild(pos)]) {
swap(pos, leftChild(pos));
maxHeapify(leftChild(pos));
}
else {
swap(pos, rightChild(pos));
maxHeapify(rightChild(pos));
}
}
}
Here, you can see the basecase of:
if (isLeaf(pos))
return;
You need to add a base case to your recursive function.

Segmentation fault when assigning integer to pointer

I'm trying to assign my node value to a pointer, but gdb gives me segmentation fault when the code is ran. What can I do?
void biggerPotion(No* node, int bottleSize, int *aux){
if(node == NULL)
return;
maiorPocao(node>left, bottleSize, aux);
maiorPocao(node->right, bottleSize, aux);
if((node->value >= garra) && (node-> value < *aux))
*aux = node->value; //here is the issue
}
Other relevant parts of the code are:
for(i=0; i< nBottles;i++){
a = 1000; //i declared that
biggerPotion(potions,bottleSize[i],&a);
}
Okay, since the errant line is:
*aux = node->value;
then either aux is the problem or node is (because they're the only two pointers being dereferenced on that line).
I would print them both out before executing that if block just to be certain:
fprintf(stderr, "node is %p, aux is %p\n", node, aux);
Given the large use of node and small use of aux, it's probably the latter that's causing the issue, in which case you should examine what you're passing to the top-level call of biggerPortion. You should post that top-level call, including the declaration of whatever variable you're passing in.
In any case, you can test that by simply changing:
*aux = node->value;
into:
{
int temp = node->value;
}
If the problem disappears then it's definitely the aux pointer being wrong somehow. Make sure you are actually passing in a pointer, such as with:
int myVar;
biggerPotion(rootNodePtr, 42, &myVar);

Calculating number of nodes in BST using recursion c++

I'm trying to find the number of nodes in a BST using recursion. Here is my code
struct Node{
int key;
struct Node* left;
struct Node* right;
Node(){
int key = 0;
struct Node* left = nullptr;
struct Node* right = nullptr;
}
};
src_root is the address of the root node of the tree.
int BST::countNodes(Node* src_root, int sum){
if((src_root==root && src_root==nullptr) || src_root==nullptr)
return 0;
else if(src_root->left==nullptr || src_root->right==nullptr)
return sum;
return countNodes(src_root->left, sum + 1) + countNodes(src_root->right, sum + 1) + 1;
}
However my code only seems to work if there are 3 nodes. Anything greater than 3 gives wrong answer. Please help me find out what's wrong with it. Thanks!
It is a long time ago since I made anything in C/C++ so if there might be some syntax errors.
int BST::countNodes(Node *scr_root)
{
if (scr_root == null) return 0;
return 1 + countNodes(scr_root->left) + countNodes(scr_root->right);
}
I think that will do the job.
You have several logical and structural problems in your implementation. Casperah gave you the "clean" answer that I assume you already found on the web (if you haven't already done that research, you shouldn't have posted your question). Thus, what you're looking for is not someone else's solution, but how to fix your own.
Why do you pass sum down the tree? Lower nodes shouldn't care what the previous count is; it's the parent's job to accumulate the counts from its children. See how that's done in Casperah's answer? Drop the extra parameter from your code; it's merely another source for error.
Your base case has an identically false clause: src_root==root && src_root==nullptr ... if you make a meaningful call, src_root cannot be both root and nullptr.
Why are you comparing against a global value, root? Each call simply gets its own job done and returns. When your call tree crawls back to the original invocation, the one that was called with the root, it simply does its job and returns to the calling program. This should not be a special case.
Your else clause is wrong: it says that if either child is null, you ignore counting the other child altogether and return only the count so far. This guarantees that you'll give the wrong answer unless the tree is absolutely balanced and filled, a total of 2^N - 1 nodes for N levels.
Fix those items in whatever order you find instructive; the idea is to learn. Note, however, that your final code should look a lot like the answer Casperah provided.

How can lParam be casted into more than one structures?

I saw this piece of code below in here. I tested it and it works all right.
// g_hLink is the handle of the SysLink control.
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) // CAST TO NMHDR*
{
case NM_CLICK: // Fall through to the next case.
case NM_RETURN:
{
PNMLINK pNMLink = (PNMLINK)lParam; // CAST TO NMLINK*
LITEM item = pNMLink->item;
if ((((LPNMHDR)lParam)->hwndFrom == g_hLink) && (item.iLink == 0))
{
ShellExecute(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
}
else if (wcscmp(item.szID, L"idInfo") == 0)
{
MessageBox(hDlg, L"This isn't much help.", L"Example", MB_OK);
}
break;
}
}
break;
The parameter lParam is casted to both NMHDR* and NMLINK* types. The documentation of WM_NOTIFY message says that lParam can be casted to NMHDR*, but NMLINK is a different structure which encapsulates NMHDR.
What does actually happen when we cast lParam to an arbitrarily chosen structure between these two?
NMLINK contains NMHDR as its first element:
struct NMLINK {
NMHDR hdr;
LITEM item;
};
And so pointer to NMLINK equals to the pointer to its first member (which is NMHDR structure sitting at offset 0), they are the same. It means that you can cast NMHDR* to NMLINK*.

Resources