-1

I'm trying to create a 3D rendering engine in C++. It works well, but I got stuck on one point

I have a struct called screenDrawInfo, defined as:

typedef struct {
    float *rectangle;
    unsigned char color[3];
} screenDrawInfo;

I also have an array of the struct.

screenDrawInfo *polygon_buffer;
int polygon_buffer_size = 0;

But whenever I try to assign an address to the pointer, like

float vertex_buffer_ssf[8] = {0, 0, 0, 0, 0, 0, 0, 0};

polygon_buffer[polygon_buffer_size].rectangle = &vertex_buffer_ssf[0];

The program hangs forever. It compiles fine though.

Full code below:

#include <iostream>

using namespace std;

typedef struct {
    float *rectangle;
    unsigned char color[3];
} screenDrawInfo;

screenDrawInfo *polygon_buffer;
int polygon_buffer_size = 0;

float vertex_buffer_wsf[12] = {
    0, 0, 0,
    0, 0, 0,
    0, 0, 0,
    0, 0, 0
};
int vertex_buffer_ws[12] = {
    0, 0, 0,
    0, 0, 0,
    0, 0, 0,
    0, 0, 0
};
float vertex_buffer_ssf[8] = {
    0, 0,
    0, 0,
    0, 0,
    0, 0
};
int vertex_buffer_ss[8] = {
    0, 0,
    0, 0,
    0, 0,
    0, 0
};

int vertex_buffer_count[4] = {0, 0, 0, 0};

void regVertF(float x, float y) {
    int count = vertex_buffer_count[2];
    if(count >= 4) {
        cerr << "[ERROR] Pixel Buffer full. Please request a polygon draw. Ignoring call." << endl;
    }
    vertex_buffer_ssf[count * 2] = x;
    vertex_buffer_ssf[count * 2 + 1] = y;
    count++;
}

void displayShapeF(int n) {
    if(polygon_buffer_size == n) return;
    polygon_buffer[polygon_buffer_size].rectangle = &vertex_buffer_ssf[0];
    vertex_buffer_count[2] = 0;
}

screenDrawInfo *get_polygon_buffer_addr() {
    return polygon_buffer;
}

int get_polygon_buffer_size() {
    return polygon_buffer_size;
}

Minimal reproducible example:

#include <iostream>

typedef struct {
    float *pointer;
} structure;

int main(int argc, char **argv) {
    float number = 4.5;
    structure *bug;
    std::cout << "You should be able to see this in the log" << std::endl;
    bug[2].pointer = &number;
    std::cout << "You shouldn't be able to see this in the log" << std::endl;
}

EDIT:

  1. There is not supposed to be any relation between the minimal reproducible code and the actual code. The full code is four files, so I tried to keep it brief.
  2. polygon_buffer_size increments only a few times, though I will make some exception handling code later on. For the moment, polygon_buffer_size maximum value is 1.
  3. I am much more accustomed to C syntax, and I would like to refrain from using STL classes.
modlegend
  • 11
  • 5
  • 2
    `bug` is not initialized. `bug[2]` is undefined. – 463035818_is_not_an_ai May 16 '23 at 11:29
  • 4
    if you want an array of `structure`s you need to create an array of `structure`s. Pointers are not arrays and arrays are not pointers – 463035818_is_not_an_ai May 16 '23 at 11:29
  • 2
    a pointer to a single float is usually a useless use of new. And I see more of that in your code. Only use new if you really have to (runtime polymorphism/virtual functions) otherwise just use class instances and pass by (const) reference. Or put objects in containers like [`std::vector`](https://en.cppreference.com/w/cpp/container/vector). If you still need to manually allocate use [`std::make_unique`](https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique). [C++ guidelines R.11](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#r11-avoid-calling-new-and-delete-explicitly) – Pepijn Kramer May 16 '23 at 11:32
  • 1
    in the other code `polygon_buffer` is a global and initialized as `nullptr`. Unless you actually allocate an array somewhere and make the pointer point to its first element `polygon_buffer[polygon_buffer_size].` is out of bounds, it is undefined behavior – 463035818_is_not_an_ai May 16 '23 at 11:33
  • 1
    you should forget that raw pointers exist. Use `std::vector` and `std::array`. Actual use cases for raw pointers are so rare that you can go a long way before you miss them – 463035818_is_not_an_ai May 16 '23 at 11:34
  • `typedef struct { float *rectangle; unsigned char color[3]; } screenDrawInfo;` ... ehr no a float* is not a rectangle you will need structs for coordinates and colors and build your rectangle from that write code with semantic meaning don't just throw in raw datatypes. – Pepijn Kramer May 16 '23 at 11:39
  • 1
    Looks like you are not learning c++ from a good source. Good sources to learn cpp from are : A [recent C++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) or have a go at https://www.learncpp.com/ (that's pretty decent, and pretty up-to-date). For C++ reference material use : [cppreference](https://en.cppreference.com/w/). And after you learned the C++ basics from those sources, look at the [C++ coreguidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines) regularely to keep up-to-date with the latest guidelines. – Pepijn Kramer May 16 '23 at 11:40
  • @PepijnKramer I am self-taught. – modlegend May 16 '23 at 11:52
  • not sure to what comments you tried to reply to. But none of your edits changes the fact that in your code `polygon_buffer` does not point to an array. `polygon_buffer[polygon_buffer_size]` is wrong. Its not clear where you expect the array to come from – 463035818_is_not_an_ai May 16 '23 at 11:55
  • 3
    "I would like to refrain from using STL classes." why? Not using `std::vector` or `std::array` is not making things simpler, but harder. – 463035818_is_not_an_ai May 16 '23 at 11:57
  • Yes, `std::vector polygon_buffer;` would be the perfect solution here. `if(polygon_buffer.size() >= n) return; polygon_buffer.emplace_back(); polygon_buffer.back().rectangle = &vertex_buffer_ssf[0];` and then small changes to the getters. And same for your `bug` issue. – stefaanv May 16 '23 at 12:10
  • 3
    @modlegend Self taught is good, but it also means you probably have run into a lot of "old style" examples (and bad practices) ;) Hope the links will help you. Also know that std::vector and std::string have been part of C++ since 1998 so use them – Pepijn Kramer May 16 '23 at 12:17
  • @modlegend *I am much more accustomed to C syntax, and I would like to refrain from using STL classes* -- C and C++ are two different languages. Do not use `C` as a model in writing proper, modern, C++ code. Things like this: `typedef struct { float *pointer;} structure;` are red flags that you're a C programmer writing C++ code without learning the differences. In C++, using `typedef` is not necessary. The only time `typedef` is used is if for some reason, the header file is used in both C and C++ programs. But if your program is pure C++, then remove the `typedef struct` stuff. – PaulMcKenzie May 16 '23 at 12:59
  • 1
    @modlegend *I'm trying to create a 3D rendering engine in C++* -- To add, your program is for a 3D rendering engine. So you have a choice -- either waste time trying to figure out pointers, or use `std::vector` and `std::string`, so that you can move forward in the creation of your application much more quickly. If your program's final goal is to create a home-made vector or string class, that's one thing, but that is not the goal of the program you are writing. – PaulMcKenzie May 16 '23 at 13:06
  • Avoid using a raw pointer as an owning pointer. Instead use `std::vector` for an array of objects, or `std::unique_ptr` for a single object. *I would like to refrain from using STL classes* I hope you reconsider, because that will end in tears in C++. – Eljay May 16 '23 at 13:14
  • @PaulMcKenzie I will take your advice for not interchangeably using C and C++, though for this project I will still be writing C in .cpp files. In my opinion, C is more understandable to my brain and thought process. – modlegend May 18 '23 at 11:22

1 Answers1

0

I found the answer.

As I do not completely understand undefined pointers, I did not know I had to dynamically allocate memory for it. Thanks to 463035818_is_not_a_number, I got the hint and dynamically allocated memory to the pointer.

I am sorry for wasting your time. I wish compilers had warnings for these things.

modlegend
  • 11
  • 5
  • 3
    sorry, but no. Do not miss the important message of my second comment: Pointers are not arrays and arrays are not pointers. You want an array, but in your code you only have an uninitialized pointer. A pointer can point to the first element of an array, but you should prefer to use a `std::vector` rather than a manually managed c-array – 463035818_is_not_an_ai May 16 '23 at 11:58
  • in other words `structure *bug;` has memory allocated for the pointer, but none for an array (because a pointer is not an array) – 463035818_is_not_an_ai May 16 '23 at 11:59
  • I'm not sure I understand, @463035818_is_not_a_number. As far as I understand, as long as memory is allocated to the pointer, it can be used as an array for most purposes. – modlegend May 16 '23 at 12:24
  • 1
    `int* x = new int[42];` there are two distinct objects here a) an array of 12 integers b) `x`, a pointer to the first element of that array. It is essential to understand that a) and b) are not the same. Confusing the two is the source of your bug. In your code you only have b) a pointer, but a) the array is missing completely – 463035818_is_not_an_ai May 16 '23 at 12:30
  • @modlegend *I got the hint and dynamically allocated memory to the pointer.* -- And now who is responsible for calling `delete`? If there is no `delete`, you now have a memory leak. – PaulMcKenzie May 16 '23 at 12:57
  • @PaulMcKenzie I am aware of freeing memory. – modlegend May 16 '23 at 15:23
  • It isn't only about freeing memory. None of the structs you posted in the question follow the [rule of 3](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three). Look at the **Managing Resources** section of that link -- does that struct/class look similar to yours? – PaulMcKenzie May 16 '23 at 15:28