objective-c 2.0 properties and 'retain' - objective-c-2.0

Stupid question, but why do we need to use 'retain' when declaring a property? Doesn't it get retained anyway when it's assigned something?
Looking at this example, it seems that an object is automatically retained when alloc'ed, so what's the point?
#import "Fraction.h"
#import <stdio.h>
int main( int argc, const char *argv[] ) {
Fraction *frac1 = [[Fraction alloc] init];
Fraction *frac2 = [[Fraction alloc] init];
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// increment them
[frac1 retain]; // 2
[frac1 retain]; // 3
[frac2 retain]; // 2
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// decrement
[frac1 release]; // 2
[frac2 release]; // 1
// print current counts
printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );
// release them until they dealloc themselves
[frac1 release]; // 1
[frac1 release]; // 0
[frac2 release]; // 0
■output
Fraction 1 retain count: 1
Fraction 2 retain count: 1
Fraction 1 retain count: 3
Fraction 2 retain count: 2
Fraction 1 retain count: 2
Fraction 2 retain count: 1
Deallocing fraction
Deallocing fraction
This is driving me crazy!

The default behavior of a property is ASSIGN, not RETAIN. These are not the same behavior. If your property is for a primitive data type, such as an int, then ASSIGN would be correct to use. However, if you specify (retain) and the property points to an object pointer such as NSObject *object, the pointer is assigned the memory address of the object and it's retain count is incremented by one. If your program consists of nothing more than a lone main function, then it's purpose is hard to see. However, suppose your class had this method:
-(void)setMyArrayWithString:(NSString *)s{
myArray = [NSArray arrayWithObject:s];
}
Suppose myArray is defined as NSArray *myArray and has the proper #property (retain) statement.
Everything works fine until the method returns. This is because the object returned from NSArray is an autoreleased object. If we don't retain it, it will be released by the NSAutoReleasePool and we won't be able to use it (and we'll get nasty bugs and bad access violations). To fix this we can do one of two things:
-(void)setMyArrayWithString:(NSString *)s{
self.myArray = [NSArray arrayWithObject:s];
// OR
myArray = [[NSArray arrayWithObject:s] retain];
}
The first solution uses self.myArray to utilize the #property definition. This code assigns and then retains the object so that we don't lose it when the function returns. The second solution sets the NSArray *myArray pointer manually and then manually retains the NSArray object. Either way the NSAutoreleasePool will release the object at the end of the function, however it won't be deallocated because we still have our retain from earlier keeping it alive.

Related

How C static pointer guards repeating work?

I'm a C new learner,
when learning llvm, I met the following code
#include <stdint.h>
#include <stdio.h>
#include <sanitizer/coverage_interface.h>
// This callback is inserted by the compiler as a module constructor
// into every DSO. 'start' and 'stop' correspond to the
// beginning and end of the section with the guards for the entire
// binary (executable or DSO). The callback will be called at least
// once per DSO and may be called multiple times with the same parameters.
void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
static uint64_t N; // Counter for the guards.
if (start == stop || *start) return; // Initialize only once.
printf("INIT: %p %p\n", start, stop);
for (uint32_t *x = start; x < stop; x++)
*x = ++N; // Guards should start from 1.
printf("%p \n", x);
}
static uint64_t N; matters
Counter for the guards.
without it, the following for loop repeats.
I know what it can do.
How does it work ?
Here is what the above code prints:
INIT: 0x104351508 0x104351544
0x104351508
0x10435150c
0x104351510
0x104351514
0x104351518
0x10435151c
0x104351520
0x104351524
0x104351528
0x10435152c
0x104351530
0x104351534
0x104351538
0x10435153c
0x104351540
after uint32_t *x = start;
why *x = ++N; does not change x's position?
why *x = ++N; does not change x's position?
It seems you are confused about "the value of a pointer" and "the value a pointer points to" (aka the value of the pointed to object).
The value of the pointer x is initialized by
uint32_t *x = start;
\---------/ \------/
Defines Initializes the value of the pointer to equal the value of start
the
pointer x
Then the value of x is changed by this code:
x++
This part
*x = ++N;
will not change the value of x. Instead it change the value of the pointed to object.
If you change
printf("%p \n", x); --> printf("%p %u\n", x, *x);
you'll see output like
INIT: 0x104351508 0x104351544
0x104351508 1
0x10435150c 2
0x104351510 3
0x104351514 4
0x104351518 5
0x10435151c 6
0x104351520 7
0x104351524 8
0x104351528 9
0x10435152c 10
0x104351530 11
0x104351534 12
0x104351538 13
0x10435153c 14
0x104351540 15
where the first column is the value of the pointer x and the second column is the value of the pointed to object.
In the question you write:
static uint64_t N; matters
Counter for the guards.
without it, the following for loop repeats.
It's a bit unclear exactly what you are asking here but using the keyword static means that the object N preserve its value between calls. In other words, if you call the function again after the example above then N will have the value 15 to start with. So if you provide a new area (i.e. new start and stop values), you could see something like:
INIT: 0x104351600 0x10435160c
0x104351600 16
0x104351604 17
0x104351608 18

C array elements change value

I define three arrays. Once the first one is allocated, I print out its first element which is as expected. Then, a second array ('problematic') is allocated. When I reprint the first array's first element, it has magically changed to the value I allocated the array 'problematic' with. It gets even weirder. Had I chosen not to allocate the array 'problematic' but 'working' between the two print statements, everything works fine.
What's going on?
#include<stdio.h>
int problem(double variable);
int main(){
problem(1.0);
return 0;
}
int problem(double variable){
int limit1 = 10;
int limit2 = 10;
double bin_bounds[limit1];
double problematic[limit2];
double working[limit2];
// Allocate first array
for (int bin=0; bin<limit1; bin++){
bin_bounds[bin] = variable/limit1 * (bin+1);
}
printf("%f\n\n",bin_bounds[0]); // prints 0.2 as excpected
for (int el=0;el<=limit2;el++){problematic[el]=2.;}
printf("%f\n\n",bin_bounds[0]); // prints 2.0
return 0;
}
It's array out of bound, you are allocating 10 elements with index 0 to 9 but you're accessing index 10. Your loop should only be
for (int el=0;el<limit2;el++){problematic[el]=2.;}
The big_bounds is probably allocated right after the problematic in this case. So problematic[10] is at the same memory address as big_bounds[0]
Run with valgrind and check whether you are accesing invalid memory.During declaring array init it with 0.

How to display all values stored in an array and how to pass those values to a second function {C}

The main object of the program is to display all the values within the array called "channels" so that the user can see all the possible choices. After I prompt the user to choose one of the four channels I need to pass those values on to second function in order to calculate something. This is what i have so far.
I also cannot use any loops.
Please help.
#include <stdio.h>
// I'm using a structure to store all the values within the array
typedef struct
{
char* name;
double n; //roughness
double slope;
double width;
double depth;
} CHANNEL;
main ()
{
CHANNEL channels [4] = {
{"Channel1", 0.035, 0.0001, 10.0, 2.0},
{"Channel2", 0.020, 0.0002, 8.0, 1.0},
{"Channel3", 0.015, 0.0010, 20.0, 1.5},
{"Channel4", 0.030, 0.0007, 24.0, 3.0}
};
//I want to display all the channels and their values right here... i know i have to use printf but would i need to use a pointer?
printf("Please note:\n 0 = Channel 1 \n 1 = Channel 2 \n 2 = Channel 3 \n 3 = Channel 4);
printf("Pick a channel from 0-3\n");
int c = 0;
scanf("%i", &c);
CHANNEL chosen = channels [c];
}
//Here is what i have for the second function so far, I have the formula on how to calculate velocity but i don't know how to pass the chosen values and also would i still need to put a function prototype at the top?
CHANNEL calculateVelocity(CHANNEL channels[])
{
double velocity;
//THIS IS THE EQUATION I NEED TO USE
//velocity = (slope/n)*(pow((width/depth)/width +2 * depth),(2/3));
}
Apart from the missing " from the printf calls (from both of them) and that you forgot the return value of the main which is this way is default int you have started pretty well.
CHANNEL chosen is now the selected channel, to use its data you have to pass it to your function. As you are going to use its values and you do not want to change them, you can pass it by value to your function.
You function should return double as velocity is double. To access the member variables the following sytnax have to be used:
double calculateVelocity(const CHANNEL selected)
{
double velocity;
double n = selected.n;
double slope = selected.slope;
double width = selected.width;
double depth = selected.depth;
//THIS IS THE EQUATION I NEED TO USE
velocity = (slope/n)*pow(((width/depth)/width +2 * depth),(2.0/3.0));
return velocity;
}
If I were you I would also check the input from the console, so you won't pass a wrong index to your channels array.
int main ()
{
CHANNEL channels [4] = {
{"Channel1", 2.0, 2.0, 10.0, 2.0},
{"Channel2", 0.020, 0.0002, 8.0, 1.0},
{"Channel3", 0.015, 0.0010, 20.0, 1.5},
{"Channel4", 0.030, 0.0007, 24.0, 3.0}
};
printf("Please note:\n 0 = Channel 1 \n 1 = Channel 2 \n 2 = Channel 3 \n 3 = Channel 4\n");
printf("Pick a channel from 0-3\n");
int c = 0;
scanf("%i", &c);
if(c < 0 || c > 3)
{
printf("Input is invalid: %d\n", c);
return 1;
}
CHANNEL chosen = channels [c];
printf("Calculated velocity: %f\n" ,calculateVelocity(chosen));
return 0;
}
and include math.h for pow.
Lets go through each of your questions one at a time. Right now, I doubt your printf statement is doing what you intend it to. To print each channel and the elements it contains, I would suggest creating a helper function, perhaps looking something like:
void CHANNEL_print(CHANNEL* channel) {
printf("%s\n", channel->name);
printf("%lf\n", n); // Note that %lf is for doubles
// print the rest of the values just like this...
}
I'm not going tho complete the function in it's entirety because it appears that this question is a homework problem of some sort (why else would you not use a loop??) and I don't want to give away the answer completely. You should be able to figure the rest out quite easily though.
As for the second function, you are correct in that a function prototype or the definition itself would be required before calling it. It appears that you only want to use one CHANNEL in the function, so your prototype should look something like
double calculateVelocity(CHANNEL* channel)
since (I assume) you want to return the velocity you calculate. The pointer should be a pointer to the channel that you want to pass to the function (i.e. &channel[c]) Then, the calculation itself inside the function would look like:
velocity = (channel->slope / channel->n) * pow((channel->width / channel->depth) / channel->width + 2 * channel->depth, 2.0/3.0)
Note that 2/3 = 0 since it's integer division, and there was an extra ) in your equation.
just a side note, you need function prototype if the definition of the function is in an external module or the definition of the function comes after a call to it.
I know you said you're not allowed to use loops, but iterating through an array is pretty much the ideal use case for using a loop. Here's how I would use a loop to display the contents of your array:
printf( "%20s%8s%8s%8s%8s\n", "Name", "N", "Slope", "Width", "Depth" );
printf( "%20s%8s%8s%8s%8s\n", "----", "-", "-----", "-----", "-----" );
for ( size_t i = 0; i < N; i++ ) // where N is the number of rows in the array
{
printf( %20s%8.3f%8.4f%8.1f%8.1f\n",
channels[i].name,
channels[i].n,
channels[i].slope,
channels[i].width,
channels[i].depth
);
This prints out a 2-line header followed by the array contents that will look something like this (I don't have a compiler handy, so I can't code it up and post output):
Name N Slope Width Depth
---- - ----- ----- -----
Channel1 0.035 0.0001 10.0 2.0
Channel2 0.020 0.0002 8.0 1.0
Channel3 0.015 0.0010 20.0 1.5
...
In your case, N would be 4.
The structure of a for loop is for ( expr1opt ; expr2opt ; expr3opt ) statement
In a for loop, expr1 is evaluated first; this expression usually initializes a loop counter or some other condition. Then expr2 is evaluated; if it evaluates to a non-zero value (true) then the body of the loop is executed. After the loop body executes, expr3 is evaluated; this usually updates the loop counter or updates some other condition. Then expr2 is evaluated again. The loop body is executed as long as expr2 evaluates to non-zero.
Any or all of expr1, expr2, and expr3 may be omitted.
A few words on the printf format strings...
A format specifier takes the form% [flags] [field-width] [. precision] [length-modifier] conversion-specifier
So, %20s means "print a string in a field that's at least 20 characters wide, padded with blanks to the left." %8.3f means print a floating point value in a field that's at least 8 characters wide including the decimal point, with no more than 3 digits after the decimal point."

Behavior of int x[size]={0}

I am reading through K&R 2nd Edition and C by Dissection 4th Edition, and came to arrays where they both didn't explicitly state it but I remember from a class that we want to always initialize an array to zero to circumvent garbage being in the indices from previous memory allocations.
I looked online and similar suggestions were made, but I saw an array declaration/initialization I hadn't seen before so I wanted to test it: int x[size]={0}; found here
I wrote a little c program to check things out, and I'm currently going down the rabbit hole it seems.
Can someone please help explain the output?
gcc is compiling to c99, -std=c89 won't compile (because of // type comments so I know it isn't c89 (ansi) ), but looking at the gcc flags I cannot find STDC_VERSION flag to tell me which is; therefore, I've manually compiled like: gcc -Wall -std=c99 -o arrayTest arrayTest.c
The little program is:
#include <stdio.h>
typedef int bool;
#define true 1
#define false 2
#define DEBUG_ true
int main()
{
int x[5] ={0};// what does this do? Guess: Initialize x[0]-x[4] values of 0?
int i=0;// for loop
printf("Hello, World!\n");
if(DEBUG_){
printf("TESTING FOR NULLITY OF INDICES\n");
for(i=0; i<5; i++){
if(x[i]==NULL) printf("The Value at %d is NULL\n", i);
}// If each is null, thats what int x[5]={0} decl/initl does..
// Is 0 NULL in C Language (I wouldn't have thought so..)
}
printf("assigning 0 to all indices of the array..\n");
for(i=0; i<5; i++){ x[i]=0; }
// assigning the array to zeros..
if(DEBUG_){
printf("printing contents of array after filling with zero's\n");
for(i=0; i<5; i++){ printf(x[i]+"\n"); }
// hopefully print out 5 zeros..
printf("SUSPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY\n");
for(i=0; i<5; i++){
if(x[i]==NULL) printf("The Value at %d is NULL\n", i);
}
}
printf("Filling the array, each index has value i*2\n");
for(i=0; i<5; i++){ x[i]= i*2; }
// initialize the array to i*2.
// Expected Values 0, 2, 4, 6, 8
for(i=0; i<5; i++){ printf(x[i]+"\n"); }
// hopefully print out Expected Values
return 0;
}
The output from the program:
-bash-4.3$
-bash-4.3$ arrayTest
Hello, World!
TESTING FOR NULLITY OF INDICES
The Value at 0 is NULL
The Value at 1 is NULL
The Value at 2 is NULL
The Value at 3 is NULL
The Value at 4 is NULL
assigning 0 to all indices of the array..
printing contents of array after filling with zero's
SUSPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
The Value at 0 is NULL
The Value at 1 is NULL
The Value at 2 is NULL
The Value at 3 is NULL
The Value at 4 is NULL
Filling the array, each index has value i*2
USPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAYPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAYCTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
From the looks of that last line there is a repeating sequence occurring:
USPECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
PECTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
CTING THAT ZERO FILL DIDN'T REPLACE NULL VALUES IN ARRAY
I am not sure why this is occurring.
Specifically can someone explain what the array declaration/initialization actually does, why assigning zeros to the array isn't working in this case, why trying to set each index to i*2 doesn't work, and what is going on with the print pattern at the end of the output?
The printf() usage is wrong here. Change
printf(x[i]+"\n");
to
printf("%d\n", x[i]);
See the man page for details.
Also, regarding the initializaion, if you need any reference, see this.
According to the C Standard (6.7.9 Initialization)
21 If there are fewer initializers in a brace-enclosed list than there
are elements or members of an aggregate, or fewer characters in a
string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration.
This means that in this declaration
int x[5] ={0};
the first element of the array is explicitly initialized by 0 and all other elements of the array are implicitly initialized the same way as objects with static storage duration that is they are also initialized by 0.
If you would wriite for example
int x[5] ={1};
then the elements of the array would be initialized like { 1, 0, 0, 0, 0 }
Also take into account that this statement
printf(x[i]+"\n");
does not do what you expect. In this expression x[i]+"\n" there is used the pointer arithmetic becuase string literal "\n" is converted to pointer to its first character and after adding to the pointer value x[i] can result in undefined behaviour. I think you mean
printf( "%d\n", x[i] );
Here is a more interesting example of initializing odd elements of an array with 1 and even elements with 0 which you do not know yet..
#include <stdio.h>
int main(void)
{
int a[] = { [1] = 1, [3] = 1, [5] = 1 };
printf( "The number of elements in the array is %zu\n",
sizeof( a ) / sizeof( *a) );
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
printf( "%d ", a[i] );
}
printf( "\n" );
return 0;
}
The program output is
The number of elements in the array is 6
0 1 0 1 0 1
Thus if for example you want to initialize only the last element of an array with 1 and all other elements with 0 you can write
int a[] = { [4] = 1 };

Proper way to count number of string elements in an array in C

This is the code I'm blundering around with.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i=0;
for(i=1;i<argc;i++){
printf("arg %i: %s\n", i , argv[i]);
}
//custom array of strings
char *states[] = {
"California", "Oregon", "Idaho", "Arkansas", "Washington",
"Texas", "Montana"
};
int num_states = sizeof(*states)-1;
printf("%i\n", num_states);
for(i=0;i<num_states;i++){
printf("state %i: %s\n", i, states[i]);
}
return 0;
}
My question is a fairly simple one, before I got this work I was encountering a very frustrating segfault.
"int num_states = sizeof(*states)-1;" this line works to return the number of string in array, minus one (not sure why the -1 is required to prevent segfault)
"int num_states = sizeof(states);" this returned 56, and caused my for loop to iterate through stuff that didn't exist.
The problem is I'm not sure what the difference is. My best guess is that the first line counts the total number of bytes that states[] is composed of, and that the second counts the number of locations in memory stored by *states.
Please correct me if my thinking is wrong. And if you can tell me why the -1 somehow prevented this segfault I'd appreciate it.
The right way to do it
The value in num_states should be:
int num_states = sizeof(states) / sizeof(states[0]);
That is, the number of elements in an array is the size of the array divided by the size of the zeroth element of the array (which is the same size as every other element of the array).
This can be generalized to handle other arrays. Harking back to Fortran and/or Basic, I often use a macro:
#define DIM(x) (sizeof(x)/sizeof(*(x)))
Be careful: this only works with arrays where the size is known. It does not work with 'arrays' passed to functions; such 'arrays' degenerate to pointers, and you end up with a wrong answer. If you defined the function in the current source file (outside any function), or in the current function, you can use this safely.
Why your code worked
As to why your example worked — the answer is 'coincidence'. It depends on the facts that:
Your array has 7 elements.
The size of a pointer is 8 bytes on your system.
The value of sizeof(*states) is 8 because *states is a char * and (on your 64-bit machine), the size of a pointer is 8. Therefore int num_states = sizeof(*states)-1; 'works' by coincidence. If you added or removed any entries from the array, or compiled the code on a 32-bit machine, then it would fail again (the exact modes of failure depending on the change in the environment), whereas computing the number of elements as shown would work correctly regardless of any of those changes.

Resources