-1

I have been trying to procedurally generate an array of arrayfire arrays. When dealing with other objects in the past I could either so something like:

className * listName = (className*)malloc(numOfObjects*sizeOf(className))

or

className ** listName = (className**)malloc(numOfObjects*sizeOf(className*))

and then use a for loop to allocate each of the things in the lists and delete them when I'm done with them.

This isn't working with arrayfire however. I have tried to do

af::array *Kernels; 
Kernels = (af::array*)malloc(Count*sizeof(af::array)); 

for(int i = 0; i < Count; i++) {
    Kernels[i] = af::range(i); 
}

Later I call:

free Kernels

This code compiles but will crash when I run it. This is what I get when it crashes:

terminate called after throwing an instance of 'af::exception' what(): ArrayFire Exception (Function does not support this data type:204): In function af_err af_release_array(af_array) In file src/api/c/array.cpp:194 Invalid type for argument 0

In function af::array& af::array::operator=(const af::array&) In file src/api/cpp/array.cpp:771 Aborted (core dumped)

I'm looking for either the correct syntax to do what I am trying to do or an alternative. I have googled around quite a bit and have not found what I am looking for.

Thanks.

  • Does this answer your question? [Behaviour of malloc with delete in C++](https://stackoverflow.com/questions/10854210/behaviour-of-malloc-with-delete-in-c) – Yksisarvinen Jan 05 '20 at 18:33
  • 1
    TL;DR - you are invoking Undefined Behaviour. You can only `delete` pointer that was allocated with `new`. Don't use `malloc` in C++ (and don't use manual memory allocation in modern C++ at all) – Yksisarvinen Jan 05 '20 at 18:35
  • No, changing the code to use free instead of delete doesn't fix it. – Daniel Drake Jan 05 '20 at 18:38
  • Don't use `malloc` in C++. `malloc` doesn't call contructor, you have to use placement `new` after that. [What is the difference between new/delete and malloc/free?](https://stackoverflow.com/questions/240212/what-is-the-difference-between-new-delete-and-malloc-free). – Yksisarvinen Jan 05 '20 at 18:40
  • My second example describes a secenerio in which you create a double pointer using malloc and then would call new for each of the guys in the list. In arrayfire you don't use something like array* obj = new range(10); It throws an error. – Daniel Drake Jan 05 '20 at 18:47
  • `af::array` is a C++ object that has to be both _allocated_, and _initialized_, then _deinitialized_ and _freed_, like `std::vector`. Doing all that manually is a dog's lunch, but C++ is designed to do that for you. Just declare the arrays on the stack like it's done in the getting started guide: http://arrayfire.org/docs/gettingstarted.htm – parktomatomi Jan 05 '20 at 18:51
  • 1
    @DanielDrake "_In arrayfire you don't use something like `array* obj = new range(10);` It throws an error._" Such statement doesn't allocate an array. It allocates a single `range` object passing `10` to its constructor. If it doesn't have a constructor, that accepts single `int` (or type, to which `int` can be converted to) - it would result in compilation error. Didn't you mean to write `array* obj = new range[10];`? – Algirdas Preidžius Jan 05 '20 at 18:53
  • In C++, class has to be initialized. You probably won't have much trouble with a simple C-like `struct`, but with a more complex class (one having non-default contructor and destructor) it will break. Initialization is normally done for you, when you declare object with automatic lifetime (on stack) or when you use `new`/`delete`. If you decide you are smarter than compiler and use `malloc`, you are in charge and you have to initialize the object yourself. – Yksisarvinen Jan 05 '20 at 18:54
  • are you talking about this kind of thing? // Arrays may be created using the array constructor and dimensioned // as 1D, 2D, 3D; however, the values in these arrays will be undefined array undefined_1D(100); // 1D array with 100 elements array undefined_2D(10, 100); // 2D array of size 10 x 100 array undefined_3D(10, 10, 10); // 3D array of size 10 x 10 x 10 My array's are not all the same size and some will be quite large. Doing something like array undefined_2D(10, 100000000); would work but it's gonna waste a bunch of memory. – Daniel Drake Jan 05 '20 at 18:55
  • Yksisarvinen, I am calling the constructor for each of the elements in the array containing arrayfire arrays. That is what the af::range(i) function is doing. – Daniel Drake Jan 05 '20 at 18:57
  • @Algirdas Preidžius, af::range() can be used to create arrays in arrayfire. http://arrayfire.org/docs/group__data__func__range.htm so what I was saying is that: af::array* data = new af::range(10); will throw an error. – Daniel Drake Jan 05 '20 at 19:04
  • Well apparently you have to use something like af::array* data = new af::array() even though the af::range function works if it's not a pointer. This doesn't really fix my problem though... – Daniel Drake Jan 05 '20 at 19:11
  • Right, so i'm still getting an error trying to do this: for(int i = 0; i < Count; i++) { Kernels[i] = af::array(); } – Daniel Drake Jan 05 '20 at 19:12
  • @DanielDrake "_so what I was saying is that: af::array* data = new af::range(10); will throw an error._" Did you read my entire comment? What do you expect `new af::range(10)` to do? As I mentioned, it tries to invoke constructor of `af::range`, with a single `int`. As you can see from a documention, there is no acceptable constructor for that. Do you want to create an array with 10 elements (as it would seem from the variable name, you are assigning to)? The correct syntax for that is `new af::range[10];`. Note: When stating that something results in an error: please provide said error. – Algirdas Preidžius Jan 05 '20 at 20:34

1 Answers1

0

So it seems like I have finally gotten a solution. It seems like using this: std::vector<af::array> Kernels; gets me all the functionality I want. It turns out that having a double pointer will compile but the functions in arrayfire are not built to deal with af::array* object pointers.