How do I allocate an array at runtime in Rust? - memory

Once I have allocated the array, how do I manually free it? Is pointer arithmetic possible in unsafe mode?
Like in C++:
double *A=new double[1000];
double *p=A;
int i;
for(i=0; i<1000; i++)
{
*p=(double)i;
p++;
}
delete[] A;
Is there any equivalent code in Rust?

Based on your question, I'd recommend reading the Rust Book if you haven't done so already. Idiomatic Rust will almost never involve manually freeing memory.
As for the equivalent to a dynamic array, you want a vector. Unless you're doing something unusual, you should avoid pointer arithmetic in Rust. You can write the above code variously as:
// Pre-allocate space, then fill it.
let mut a = Vec::with_capacity(1000);
for i in 0..1000 {
a.push(i as f64);
}
// Allocate and initialise, then overwrite
let mut a = vec![0.0f64; 1000];
for i in 0..1000 {
a[i] = i as f64;
}
// Construct directly from iterator.
let a: Vec<f64> = (0..1000).map(|n| n as f64).collect();

It is completely possible to allocate a fixed-sized array on the heap:
let a = Box::new([0.0f64; 1000]);
Because of deref coercion, you can still use this as an array:
for i in 0..1000 {
a[i] = i as f64;
}
You can manually free it by doing:
std::mem::drop(a);
drop takes ownership of the array, so this is completely safe. As mentioned in the other answer, it is almost never necessary to do this, the box will be freed automatically when it goes out of scope.

Related

DirectX compute shader: how to write a function with variable array size argument?

I'm trying to write a function within a compute shader (HLSL) that accept an argument being an array on different size. The compiler always reject it.
Example (not working!):
void TestFunc(in uint SA[])
{
int K;
for (K = 0; SA[K] != 0; K++) {
// Some code using SA array
}
}
[numthreads(1, 1, 1)]
void CSMain(
uint S1[] = {1, 2, 3, 4 }; // Compiler happy and discover the array size
uint S2[] = {10, 20}; // Compiler happy and discover the array size
TestFunc(S1);
TestFunc(S2);
}
If I give an array size in TestFunc(), then the compiler is happy when calling TestFunc() passing that specific array size but refuse the call for another size.
You cannot have function parameters of indeterminate size.
You need to initialize an array of know length, and an int variable that holds the array length.
void TestFunc(in uint SA[4], in uint saCount)
{ int K;
for (K = 0; SA[K] != 0; K++)
{
// Some code using SA array, saCount is your array length;
}
}
[numthreads(1, 1, 1)]
void CSMain()
{
uint S1count = 4;
uint S1[] = {1, 2, 3, 4 };
uint S2count = 2;
uint S2[] = {10, 20,0,0};
TestFunc(S1, S1count);
TestFunc(S2, S2count);
}
In my example I have set your array max size as 4, but you can set it bigger if needed. You can also set multiple functions for different array lengths, of set up multiple passes if your data overflows your array max size.
Edit to answer comment
The issue is that array dimensions of function parameters must be explicit as the compiler error states. This cannot be avoided. What you can do however, is avoid passing the array at all. If you in-line your TestFunc in your CSMain, you avoid passing the array and your routine compiles and runs. I know it can make your code longer and harder to maintain, but it's the only way to do what you want with an array of unspecified length. The advantage is that this way you have access to array.Length that might make your code simpler.

Setting Integer value in Objective c

I have recently started programming in iOS.. I am going through a code snippet that declares the following variables:
int rc = 0X00;
sqlite3_stmt *pStmt = 0X00;
FMStatement *stat = 0X00;
BOOL abc = 0X00;
what does this mean?? I read somewhere that setting 0X00 in a reference variable means setting it to NULL (in C). But what does setting a BOOL type variable and an int type variable to 0X00 mean??
I suggest you read up about the basics of programming languages, specifically, C programing with pointers. Objective-C is a superset of C and follows many similar rules.
But to your question:
The 0x in front of the literal values in the code (0x00) specifies that the value is interpreted as hexadecimal rather than decimal. But 0x00(hex) is the same as 0(dec).
int rc = 0x00; //same as int rc = 0;
int is a primitive type in both Obj-C and C that specifies an integer, effectively you are initializing the variable. In the C language you must initialize variables otherwise they could be pointing at a random piece of memory.
Therefore, examine this code:
int a;
int b = 0;
//a is NOT equal to b!
In C, the variable 'a' has not be initialized and therefore its not typically safe to assume that it will be initialized to 0. Always initialize your variable.
If you did a printf, or an NSLog of the variable 'a' you will see that it prints some huge number and it doesnt make sense (sometimes this is compiler dependent)
The same can be said for a BOOL. Although setting a BOOL to 0 is the same as setting it to false;
BOOL flag = 0; //The same as saying BOOL flag = false;
Now for the final part of your code:
FMStatement *stat = 0X00;
Often in Objective-C if you are dealing with pointers and objects you need to initialise the pointer to point at some memory address. The actual memory address is usually determined by the stack/heap and you don't need to worry about that. But you do need to ensure that the pointer isn't pointing to the wrong location (known as a garbage pointer).
To do this, we simply set our pointer to nil. eg:
FMStatement *stat = nil; //This pointer is now safe. Although memory still hasnt been allocated for it yet
This is usually taken care of for you though when you immediately allocate the memory for an object, therefore in this case you don't need to worry about initializing the pointer to nil:
FMStatement *stat = [[FMStatement alloc]init];
Like I said, I recommend you read about basic C programming, allocations, pointers, datatypes, initialising etc, once you have a grasp of this, then move to Objective-C which then builds ontop of it with Object-Oriented stuff.
Good luck.
0X00 is simply 0 in hexadecimal notation. So,
int rc = 0X00;
is the same as
int rc = 0;
Same for BOOL variables, where 0 is the same as NO. Using 0X00 is odd -- it'd make more sense to use 0 or NO where appropriate, and use nil for the pointers.

Assign value is garbage or undefined

I have posted screenshot of my error code.
heights output
please any one can help me?
I think the static analyzer is not seeing how _numberOfColumns can become non-zero, and hence its insistence that garbage is being assigned. You need to check that you are actually providing some means for _numberOfColumns to become non-zero.
Generally when I am writing loops that want to find the largest or the smallest value, I initialize the size variable to the largest (if I want the smallest) or smallest (if I want the largest) amount, and I think this will solve most of your issues:
float shortestHeight = FLT_MAX;
for (unsigned i = 0; i < _numberOfColumns; i++)
{
// etc.
}
The analyzer is correct. Your code will access garbage memory if _numberOfColumns is 0, thus allocating 0 bytes for heights, making heights[0] garbage. The analyzer doesn't know what values _numberOfColumns can have, but you can tell it by using assert(_numberOfColumns>0).
Take this C program for example:
int main(int argc, const char * argv[])
{
int n = argc-1;
int *a = malloc(n*sizeof(int));
for (int i=0; i<n; i++) {
a[i] = i;
}
int foo = a[0];
free(a);
return foo;
}
the size of a is determined by the number of arguments. If you have no arguments n == 0. If you are sure that your program (or just that part of your program) will always assign something greater than 0 to a, you can use an assertion. Adding assert(n>0) will tell the analyzer exactly that.

Why the need to use enif_compare?

Why does
int enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)
need to be used instead of just
if( lhs == rhs ) return 1;
I believe it matters that I am comparing atoms.
ERL_NIF_TERM is an opaque datatype and, to the best of my knowledge, is more akin to a pointer than a value. In fact, here's the definition: typedef unsigned long ERL_NIF_TERM (technically there are a few variants, but they're all integers with the same size as a memory address on the system)
So, you must use enif_compare for the same reason you must use str_cmp when comparing C strings: the referenced values may be identical, but the values you get are not representative of that.
Consider:
char a[] = "test";
char b[] = "test";
printf("%d\n", a == b);
Logically, you and I know that the strings are identical, but the values a and b are actually pointers to the contained value. So when you do a regular compare (==), it's comparing the pointers, not the underlying value. Since they are distinct values within the function, they are allocated to different memory addresses, and as a result, a != b, but str_cmp(a, b) == true

I don't know what patterns of block I should avoid for the literal scope in objective-c

It is said in apple's documents:
A block literal (that is, ^{ ... }) is the address of a stack-local data structure that represents the block. The scope of the stack-local data structure is therefore the enclosing compound statement, so you should avoid the patterns shown in the following examples:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: The block literal scope is the "for" loop.
}
//for example I invoke the block here
blockArray[1]();
}
void dontDoThisEither() {
void (^block)(void);
int i = random():
if (i > 1000) {
block = ^{ printf("got i at: %d\n", i); };
// WRONG: The block literal scope is the "then" clause.
}
// ...
}
I don't know what patterns I should avoid.
It seems like that I could invoke the block at which has the same literal scope as the block definition, for example behind the "if" or "for" statement.
Could you please help me to explain it?
Here it is the link https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1
I think an analogy to pointers is as following.
void foo() {
int *block = NULL;
{
int a;
block = &a;
}
// `block`, even though defined here, points to
// an invalid memory address.
}
Generally, the block literal itself only exists in the block it is defined in, so when leaving that block, the literal disappears (like the variable a did in the example above), and you're left with a dangling pointer.
For this reason, blocks are usually copied into the heap for future use. Non-ARC code uses block_copy and friends. Copying into the heap also captures all relevant variables your block uses (which might create retain-cycles).
In practice, all of this is quite shunned away by the use of ARC, properties and classes. You define a copy property in your class, and then just assign blocks to it. If you let the compiler generate the getter/setter, your block literal will automatically be copied into the heap.
#interface Bla : NSObject
#property (nonatomic, copy) void (^blockProperty)(int i);
#endf
...
Bla *bla = [[Bla alloc] init];
{
bla.blockProperty = ^(int i) { printf("%d", i); };
}
// bla.blockProperty now points to a heap copy of the block literal from above,
// so it's not dangling.
I was reading apple's documentation on blocks and did a little more research on this part. It looks to me with ARC the second example code is totally fine. I didn't try the first example. The general idea in the accepted answer is correct. However, with ARC, when you assign the literal block (NSStackBlock) to a local variable, the block is copied to heap, and if you inspect the block, you'll see it's indeed a NSMallocBlock. I also referenced this blog on this topic https://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

Resources