I have an OpenGL program, but can't alloc correctly.
m_VertexData = (GLfloat*)malloc(sizeof(m_TempVertexData));
m_NormalData = (GLfloat*)malloc(sizeof(m_TempNormalData));
NSLog(#"sizeOfTempVertex: %d sizeOfTempNormal: %d", sizeof(m_TempVertexData),sizeof(m_TempNormalData));
NSLog(#"sizeOfVertex: %d sizeOfNormal: %d",sizeof(m_VertexData),sizeof(m_NormalData));
NSLog:
sizeOfTempVertex: 432 sizeOfTempNormal: 432
sizeOfVertex: 4 sizeOfNormal: 4
sizeof tells you the size of the type (calculated at compile-time). It tells you nothing about how much memory was allocated dynamically.1
1. Except in the special case of C99's variable-length arrays.
m_VertexData and m_normalData are pointers, so their size is sizeof (whatever type it has *), so it allocates the correct amount of memory. You need to allocate sizeof(member of the array) * number of items bytes of memory. By the way, a few things related to malloc:
Don't cast the return value of malloc. It makes code unreadable and it's unnecessary as void * is implicitly promoted to whatever pointer type it is assigned to.
Don't use sizeof(type), rather sizeof(variable). If you ever change the type of the variable, it's gonna cause hard-to-track-down errors.
Considering these points, use the following code:
m_VertexData = malloc(sizeof(*m_VertexData) * numberOfItems);
According to the C standard, Section 6.5.3.4.2:
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. The result is an integer. If the type of the operand is a variable length array
type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.
In your case, the operands m_VertexData and m_NormalData are pointers (which makes sense, because you have just assigned to them the result of calling malloc). Therefore, their size is the same as the size of any other pointer on your system - 4 bytes.
In case you are wondering, there is no standard way to determine how much memory you have malloc-ed; if you need that size for future reference, you need to store that number in a separate variable.
sizeof may not work how you think it works. sizeOfVertex and sizeOfNormal are both 32-bit pointers, so 4 is the correct size for both of them. There's no portable way to determine the actual size of the allocated memory; see determine size of dynamically allocated memory in c.
Related
Let's say I have the following:
MyClass *__strong*matches = (MyClass*__strong*)calloc([myArray count], sizeof([MyClass class]));
If I would like to refer to the second pointer in matches, would I write matches[1] or would I write matches[4]? I am confused because I know that pointers take up 4 bytes, but my program crashes due to a memory error if I follow the logic of matches[4] and my program works perfectly when filling matches if I follow the logic of matches[1].
Furthermore, which would apply if I used malloc instead of calloc?
It is matches[1] because the compiler knows from the type (MyClass * __strong *matches) the size of the items (pointers in your case) that the pointer is pointing at and uses that to determine how to compile the index operation.
For comparison consider int x[4] vs. char y[4], indexing does not mean "byte offset 4" from the start of the array but "item 4" where item in this case is an int (probably 4 or 8 bytes) or char (1 byte). You have pointers (probably 4 or 8 bytes) in your "array" and the compiler knows that from the type.
HTH
In my header, I declared a few variables as #property (nonatomic) NSInteger *soldWindows; and used them to keep track of counts, incrementing with _soldWindows++;. The result consistently came out 8 times what it should be. I figured out my problem was declaring it as a pointer, so I changed it to #property (nonatomic) NSInteger soldWindows; which solved my problem.
My question is, if it was just storing a memory address, why was the integer value scaled by 8 instead of being an arbitrary address?
A pointer points to a place in memory. When you increment a pointer like this, you increment the value of the pointer, to point to a new place in memory. Given this, you can use pointer arithmetic to iterate through successive elements in an array, by dereferencing an incremented pointer. So, you're not incrementing by 1, but rather, by the size of the type of your pointer. An NSInteger is nothing more than a 64 or 32 bit int, depending on platform. In this case, it seems to be 64 bits, which is 8 bytes. This is where your 8 bit "scaling" was coming from.
Conclusion: your fix is correct!
I declared a few variables as [...] NSInteger *soldWindows; and used them to keep track of counts.
You are misusing the concept of a pointer. In C, a pointer is the address of an object in memory. In your use case there is no object being pointed to—just the address that point's to nowhere.
While this is not a problem as long as you don't dereference the pointer it's still confusing (and does not help in any way). A simple integer (like int or NSInteger) is a better choice.
why was the integer value scaled by 8?
The reason for this is called pointer arithmetic. Every C pointer has a type. The type describes the object in memory where the pointer holds the address of. When you increment a pointer, the compiler actually adds the size of the object to the pointer, so that it points to the object right after the previous one.
The size of NSInteger (in 64 Bit iOS) is 64 bit = 8 bytes. That's why incrementing an NSInteger * actually adds 8 to it.
How can I specify that a method should take as parameter a pointer to a location in memory that can hold a specified number of values? For example, if I have:
- (void)doSomethingWith:(int *)values;
I'd like to make it clear that the int * passed in should point to an allocated space in memory that's able to hold 10 such values.
To directly answer your question, use an array argument with a bounds, e.g.:
- (void)takeTenInts:(int[10])array
Which specifies that the method takes an array of 10 integers.
Only problem is the C family of languages do not do bounds checking, so the following is valid:
int a[10], b[5];
[self takeTenInts:a]; // ok
[self takeTenInts:b]; // oops, also ok according to the compiler
So while you are specifying the size, as you wish to do, that specification is not being enforced.
If you wish to enforce the size you can use a struct:
typedef struct
{
int items[10];
} TenInts;
- (void)takeTenInts(TenInts)wrappedArray
Now this doesn't actually enforce the size at all[*], but its as close a you can get with the C family (to which the word "enforcement" is anathema).
If you just wish to know the size, either pass it as an additional argument or use NSArray.
[*] It is not uncommon to see structures in C following the pattern:
typedef struct
{
// some fields
int data[0];
} someStruct;
Such structures are dynamically allocated based on their size (sizeof(someStruct)) plus enough additional space to store sufficient integers (e.g. n * sizeof(int)).
In other words, specifying an array as the last field of a structure does not enforce in anyway that there is space for exactly that number of integers; there may be space for more, or fewer...
Why use "(int *)" when you have the power (and "count") of "NSArray" to work with?
But anyways, looking at this potentially related question, couldn't you just do a "sizeof(values)" to get the size of a statically/globally allocated pointer?
If that doesn't work (which would be in the case of a dynamically allocated array), you really would probably need some kind of "count:" parameter in your "doSomethingWith:" method declaration.
There are a several ways. You could just name the method appropriately:
- (void)doSomethingWithTenInts:(int *)tenInts;
Or you could use a struct:
typedef struct {
int values[10];
} TenInts;
- (void)doSomethingWithTenInts:(TenInts *)tenInts;
Or you could make the user tell you how many ints he is giving you:
- (void)doSomethingWithInts:(int *)ints count:(int)count;
I'm having a issue getting the size of a struct pointer after allocating the memory using malloc or realloc. I've worked around this by keeping track of the memory in a separate counter, but I would like to know if this is a bug or if there is a way to properly query the size of a struct pointer.
Sample code demonstrates that no matter how much memory I allocate to the struct pointer it always returns 4 when querying using the sizeof() method.
typedef struct {
int modelID;
int bufferPosition;
int bufferSize;
} Model;
Model *models = malloc(10000 * sizeof(Model));
NSLog(#"sizeof(models) = %lu", sizeof(models)); //this prints: sizeof(models) = 4
4 is the correct answer, because "models" is a pointer, and pointers are 4 bytes. You will not be able to find the length of an array this way. Any reason you're not using NSArray?
If I understand you correctly you want to get at the size of the allocated buffer.
sizeof if the wrong way to go since it is evaluated at compile time. The size of the buffer is a runtime concept.
You would need a way to query you C library to return the allocation size for the pointer to the buffer.
Some systems have a way to get that kind of information, for instance malloc_size on Mac OS.
4 is the correct answer.
Pointers point to a memory location which could contain anything. When you are querying the size of a pointer, it gives the size of the memory location which holds the pointer, which in your case is 4.
For example
int *a = pointing to some large number;
int *b = pointing to a single digit number;
In the above case, both a and b have the same size irrespective of where they are pointing to.
For more information, have a look at this post size of a pointer
sizeof(myvar) will return size of pointer. in 32bit environment it equals to 4(bytes).
why don't you use sizeof (Model) instead?
I want to create a custom dictionary that does not copy its keys (just retains).
Internally, I plan to use an NSMutableArray with a special Pair object, where the first object of the pair is the key, and the second is the value.
Keys are all unique.
In order to quickly retrieve objects on keys, I'd use binary search algorithm - so the array should be SORTED (attention!) on memory addresses of pairs' first objects.
(btw, this is why I refused to use CFDictionaryRef with a special set of callbacks - I suspect it to degrade to O(n) in case when a reasonable hash would not be provided)
Is this a bad idea, assuming that:
Objects used as keys may change internally (that is, I cannot use isEqual: instead of address comparison);
Objects used as keys are NOT going to be deallocated (which is reasonable - they are retained by a special Pair object, and the Pair is retained by an internal NSArray).
Why is it bad (or good)?
How do I obtain memory address from a pointer? Just cast it to a long long int or something like that?
Thank you!
To get an integer value from a pointer, cast to intptr_t or uintptr_t. These types are defined in <stdint.h> and are explicitly guaranteed to be large enough to hold the value of a pointer.
I assume that pointers in objective-c are similar to c/c++. I have built sorted arrays of memory addresses to use for looking up a stack trace. On a 64 bit machine, it should be cast to whatever scalar variable is 64 bits, probably a long int. Or if you can use a uint64_t type, it will guarantee the correct size. For a 32 bit machine, use an unsigned 32 bit integer, or a uint32_t. You can use the > < >= <= = and - operators on pointers and you can also use the + operator with a pointer and an integer.