21

The issue is an "Access violation writing location 0x00000000" error message right after I initialize the bk variable to NULL. My guess is I should reserve memory space in advance to assign NULL ( something like Book bk = new Book(); ) but I have not been able to figure out how to do it in C++ till now.

Book.h

#ifndef Book_H
#define Book_H

struct _book;
typedef _book* Book;

Book CreateBook(unsigned int pageNum);

Book.cpp

#include "Book.h"
#include <iostream>

#ifndef Book_CPP
#define Book_CPP

using namespace std;

struct _book
{
    int pageNum;
};

Book CreateBook( unsigned int pageNum){

    Book bk = NULL; 

    bk->pageNum = pageNum;

    return bk;
};
6
  • 5
    Why not do object oriented programming? c++ certainly has support for it! Commented Sep 26, 2013 at 18:11
  • You shouldn't use typedef to declare pointer types! Commented Sep 26, 2013 at 18:12
  • First, you talk about C++ but you flagged your post as C, too. C++ and C are rather different languages (despite all too common beliefs). Second: "... back to a lower level programming language...", unless you program C++ as it were C, C++ is fairly high level, although a more tricky one compared to more "user friendly" ones, like Java (for example). Commented Sep 26, 2013 at 18:29
  • 1
    @LorenzoDonati Doubt that Java is 'more user friendly' (despite garbage collection, which also always does for you what you might believe), it's just different. Otherwise I fully agree. Commented Sep 26, 2013 at 18:45
  • 1
    @g-makulik Well, that's why I quoted that "user friendly". It was meant to be contrasted with "a more tricky one" (too few room in a comment to go into details :-). Of course I didn't mean, say, Java anonymous inner classes syntax is user friendly ;-) Commented Sep 26, 2013 at 19:06

8 Answers 8

26

You're assigning bk to NULL and then trying to access a member of it. That's the same as a null pointer in Java, and what you're doing would typically raise a NullPointerException (thanks from the comments). If you want to create a pointer to your struct, you need to use operator new:

bk = new _book;
// ...
return bk;

and then make sure you call delete on the pointer when you're done with it.

I would advise against using pointers here, though. Unlike other languages, C++ lets you create objects by value. It also allows for references and pointers, but only use pointers when you absolutely must. If you simply want to create a book object with a given pageNum, you should create a constructor while you're at it:

struct _book {
    int pageNum;
    _book(int n) : pageNum(n) // Create an object of type _book.
    {
    }
};

and then you can invoke it like

_book myBook(5); // myBook.pageNum == 5

If you're new to C++, please get yourself a good book on it. It's not just a low-level language, and it's also not just an OOP language. It's a multi-paradigm swiss army knife language.

Sign up to request clarification or add additional context in comments.

6 Comments

They call it a null reference, but trying to call a method via a null reference throws a NullPointerException :)
More like a swiss army machette. Very useful, very powerful, very dangerous.
Mhm. C++ is a swiss army machete wielded by an alligator, who can also throw exceptions.
@bstamour Thanks, I quickly fixed the error by using new _book to reserve memory.
No problem. Consider whether you really need to dynamically allocate it though. As mentioned C++ allows you to create instances of your classes as values on the stack, unlike other OOP languages where objects always have to be pointers.
|
4

This is what you need:

Book CreateBook( unsigned int pageNum){

    Book bk = new _book();

    bk->pageNum = pageNum;

    return bk;
}

your bk was null and you cannot access pageNum when the pointer is null.

And don't forget to call delete on bk when you are done using it.

2 Comments

As someone pointed out, I missed the typedef, updated my answer
@qxixp do you not need to declare a pointer return type for the function declaration? The declaration says you're returning type Book but the value returned is actually a pointer to Book correct? So how does the caller know which one you returned if it's not specified in the function declaration?
2

Book.h

#ifndef Book_H
#define Book_H

// why not put the layout here?    
struct Book
{
    int pageNum;
};
Book CreateBook(unsigned int pageNum);

#endif

Book.cpp

#include "Book.h"

// no #define guards
// do not using namespace std;, it is a bad habit

Book CreateBook( unsigned int pageNum){
  Book bk;
  bk.pageNum = pageNum;
  return bk;
};

This is the simplest solution. Books are actual values, and can be copied and moved around and the like.

If you need the opacity of an abstract type, only then should you deal with pointers. When you do deal with pointers, hiding them behind a typedef is a bad idea: pointers mean resource management, so it should be obvious that you are using them.

The pointer-based version:

#ifndef Book_H
#define Book_H

// why not put the layout here?    
struct Book;
Book* CreateBook(unsigned int pageNum);

#endif

* Book.cpp *

#include "Book.h"

// no #define guards
// do not using namespace std;, it is a bad habit

Book* CreateBook( unsigned int pageNum){
  Book* bk = new Book;
  bk->pageNum = pageNum;
  return bk;
};

but, if you are creating stuff, you should probably create smart pointers:

#include <memory>
std::shared_ptr<Book> CreateBook( unsigned int pageNum){
  std::shared_ptr<Book> bk( new Book );
  bk->pageNum = pageNum;
  return bk;
};

Comments

0

In

Book bk;

bk is a pointer

Allocate memory for it first

Book bk* = new _book();

And then do

bk->pageNum = pageNum;

Also don't forget to free the memory using

delete bk;

Comments

0

Why are you doing the typedefing? It can be good practice in some cases for some reason I guess.

In case you didn't know, you could also write just:

_book book;

Now book is allocated statically on the stack instead of dynamically in the heap. It'll get destroyed automatically when the variable goes out of scope just like int or double, etc...

This is useful sometimes if you want to avoid the overhead or work of allocating memory for something really simple. It was weird for me to go into Java and have to say,

vec3 position = new Vec3(0.0, 1.0, 5.0);

instead of just saying

vec3 position(0.0, 1.0, 5.0);

like you would in C++.

Comments

0
struct Book{
    int pageNum;    
};

Book* createBook(int pageNum){
    Book *result = new Book;
    result->pageNum = pageNum;
    return result;
}

int main(int argc, char** argv){
    Book book;
    book.pageNum = 0;
    return 0;
}

or

struct Book{
    int pageNum;    
    Book(int pageNum_ = 0)
    :pageNum(pageNum_){
    }
};

Book* createBook(int pageNum){
    return new Book(pageNum);
}

int main(int argc, char** argv){
    Book book(0);
    return 0;
}

Comments

0

but if you dont want to create a variable from heap then, you can directly create and return this way

bk = _book{any_data_that_you_want_to_insert};
// ...
return bk;

Comments

-1

There are a few mistakes in your code.

  1. You need to put an #endif at the end of your header file.
  2. You need to place a semicolon at the end of struct, class and union definitions (after the closing brace).
  3. You shouldn't be using pointers at all in such a simple use case.

Example:

Book.h

#ifndef BOOK_H
#define BOOK_H

struct Book
{
    int pageNum;
};

Book CreateBook(int pageNum);

#endif

Book.cpp

#include "Book.h"

Book CreateBook(int pageNum)
{
    Book bk;

    bk.pageNum = pageNum;

    return bk;
}

You don't need the CreateBook function anyway but I left it in anyway.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.