You are here:

C++/compiler errors

Advertisement


Question
QUESTION: hi,

I've encountered errors in my program.

here's some parts of the codes..

//definitions in aubio_priv.h
/* Memory management */
#define AUBIO_MALLOC(_n) malloc(_n)
#define AUBIO_REALLOC(_p,_n) realloc(_p,_n)
#define AUBIO_NEW(_t)   (_t*) malloc(sizeof(_t))
#define AUBIO_ARRAY(_t,_n)(_t*) malloc((_n)*sizeof(_t))
#define AUBIO_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)
#define AUBIO_MEMSET(_dst,_src,_t) memset(_dst,_src,sizeof(_t))
#define AUBIO_FREE(_p) free(_p)   

//part of sample.cpp where some of the errors occur.
#included aubio_priv.h
#included sample.h

fvec_t * new_fvec( uint_t length, uint_t channels) {
 fvec_t * s = AUBIO_NEW(fvec_t); //first error
 uint_t i,j;
 s->channels = channels;
 s->length = length;
 s->data = AUBIO_ARRAY(smpl_t*,s->channels); //second error
 for (i=0; i< s->channels; i++) {
   s->data[i] = AUBIO_ARRAY(smpl_t, s->length); //third error
   for (j=0; j< s->length; j++) {
     s->data[i][j]=0.;
   }
 }
 return s;
}

//these are the errors.

1> error C3861: 'malloc': identifier not found
1> error C3861: 'malloc': identifier not found
1> error C3861: 'malloc': identifier not found

Thanks.

Hazel

ANSWER: --------------------------------------------------------------------
See end for added follow up text...
--------------------------------------------------------------------

Well other than you appear to be asking about code that appears to be pure C (probably compiled as C++ though) of a C++ expert I would say that the answer is staring you in the face. The errors are _not_ unidentified errors they are:

   'malloc': identifier not found

You are using malloc (even if indirectly through #define macros). The compiler has not been told about malloc, so has no idea about what this malloc thing is. As malloc is used as a name of something the compiler presumes it identifies something (in fact a function, but the compiler does not know this as it has no information on the name), and thus calls it an identifier.

Unlike new and delete in C++, malloc, free and their relations in C are part of the C library and when used from C++ the compiler has to be told about them before you use them - that is the compiler needs to have seen a declaration for them at least - if not a full definition (not reasonable of course for library functions). This differs from C (in which function names cannot be overloaded) where a function's prototype (declaration) can be inferred from its first use in a compilation (i.e. first call site) - woe betide you though if you get this call wrong!

If you check the small print you will note that malloc in C is declared in the stdlib.h header. In C++ this is the cstdlib header. So try including this header before the aubio_priv.h header:

   #include <cstdlib>          // for malloc, free etc.
   #include "aubio_priv.h"

   // ...

Looking at your code I see you use something called #included. I have no idea what #included is nor why the header names/paths were not enclosed either in " and " (for non-system headers) or < and > (for system headers - which I usually take to mean the language library and operating system headers - if available). Hence I presume the code you posted was not that you were actually compiling. If it were compiled with say the current Microsoft compiler (Visual C++ 2008) you would have received an error similar to:

   fatal error C1021: invalid preprocessor command 'included'

Also you have an extraneous decimal point after the 0 in the line:

     s->data[i][j]=0.;

This should give you a double to uint_t conversion possible loss of data or similar warning. Use a high warning level and take note of warnings when compiling your code.

Hope this helps and moves you forward.



----------------------
FOLLOWUP
----------------------

After I posted my answer it occurred to me that in this case you could almost certainly just as well place #include <cstdlib> _after_ the other included headers - so long as they do not actually use (mainly calling) malloc, free or any of the macros that use them, which would be true if these were pure standard C89 header files, as such files tend not to contain any function definitions (i.e. code), unlike C++ (and in fact C99) headers which may contain inline function definitions (in which case the header should include cstdlib and any other headers it relies on).

[note:

For C++ we also have templates for functions and classes which are often defined entirely in their headers and have even more complex interactions with other types and values and any headers that may thereby be involved which I do not think it worth getting into here.

-- end note]

Oh and looking at the other macros you showed in your question you might also require <cstring> (<string.h> for C) for memcpy and memset (AUBIO_MEMCPY and AUBIO_MEMSET macros).

I played safe in the original question as I was not sure if sample.h was local to your project and maybe contained C++ code that used malloc, free etc. in a way that required them to be declared and did not itself include cstdlib. However, in general I include headers in the following order:

   - header specifically related to this file if any
       (e.g. if including files in somefile.cpp then maybe related header is somefile.hpp)
   - any required other current project specific headers
   - any required local library headers
   - any required third party library headers
   - any required language library headers
   - any required operating system API/library headers

The reason for this ordering is to help ensure that all local project and library headers are stand alone - that they do not rely on having other headers included before them. The header file directly related to the file in question, if any, is included first. If such a header relies on other headers and does not include them then the compiler will complain (this by the way can be a good way of finding out exactly which headers such a header requires - start with it including none and keep adding headers as indicated by compiler whinges until it compiles cleanly).

Similarly, although not so air tight, if any local project headers require a library or API header or if a local library header requires a non-local library or API header then the compiler will complain. Obviously if other project or local library headers include other headers from the project or library this is not perfect.

The order of third party, language, and operating system library and API headers is less important as they should be in a good usable state anyway. However it seems logical as third party headers may use language and operating system headers, and language headers may require operating system headers (not true in all cases).

Hope your project goes well.



---------- FOLLOW-UP ----------

QUESTION: Hi,

Thanks for the answer. It helps.

i got to solve the 'malloc' error.

I have another problem with these errors.

--error C2057: expected constant expression
--error C2466: cannot allocate an array of constant size 0
--error C2133: 'buf' : unknown size

here's some of the codes.

//pitchschmitt.h

#ifndef _PITCHSCHMITT_H
#define _PITCHSCHMITT_H


#ifdef __cplusplus
extern "C" {
#endif

typedef struct _aubio_pitchschmitt_t aubio_pitchschmitt_t;

smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input);
aubio_pitchschmitt_t * new_aubio_pitchschmitt (uint_t size, uint_t samplerate);
void del_aubio_pitchschmitt (aubio_pitchschmitt_t *p);


#ifdef __cplusplus
}
#endif

#endif /* _PITCHSCHMITT_H */


//pitchschmitt.cpp
//part where i got those errors

#include <cstdlib>
#include "aubio_priv.h"
#include "sample.h"
#include "pitchschmitt.h"

smpl_t aubio_pitchschmitt_detect (aubio_pitchschmitt_t *p, fvec_t * input)
{
 signed short int buf[input->length];//errors occur here
 uint_t i;
 for (i=0; i<input->length; i++) {
   buf[i] = input->data[0][i]*32768.;
 }
 return aubio_schmittS16LE(p, input->length, buf);
}


Thanks again.

Answer
[Note:

Code shown in this answer is for demonstration and exposition purposes only. It is _not_ intended for production use. Much of such illustrative code has not even been compiled and so may contain errors - typos etc. If so the I apologise.

--end note]


Well if you _read_ what the errors say - especially the first one you will see that it says "expected constant expression". The others refer to arrays and buf. These should be _huge_ clues.

You cannot define automatic (local stack based) or static (local and global static) arrays using variable sizes for the dimensions, i.e. sizes known only at runtime.

This is because the compiler needs to know the size of all such objects at compile time. In this case then we can see that the compiler needs to know the value of the dimension for buf, and input->length is in no way constant and so the compiler has no idea of what its value will be.

Hence buf needs to be allocated dynamically (or you need to define an automatic array with a large enough fixed size for most cases and check that the value required in each call does not exceed this limit). Usually I would say use C++ idioms to do this but I notice you pass it to one of the aubio functions - so you may have to use the aubio macros for allocating memory to do so (was it AUBIO_MALLOC or similar wasn't it?) - see next couple of paragraphs.

In fact this brings up a second potential problem with the code as is: you are passing a locally allocated buffer to this function. You need to read _very_ _very_ carefully the documentation for such functions to ensure they do not hold onto such pointers and use them after calls to them return. As buf will go out of scope when your function returns (pretty much as soon as the call to aubio_schmittS16LE returns) and be destroyed if the aubio library attempts to use this memory later very bad wackiness ensues - i.e. it will try to read, or worse modify, memory no longer allocated to the buffer array whose pointer it was passed.

If aubio_schmittS16LE does hold onto the pointer to buf then does it also take ownership of this buffer (I would expect this to be so)? Ownership means having responsibility to release a resource when done with it. If it does then you _will_ have to ensure you allocate the buffer array in the way aubio_schmittS16LE expects (presumably using AUBIO_MALLOC or similar), as the allocation/creation method you use has to match the destruction/release method used by aubio_schmittS16LE or whatever part of aubio releases the buffer memory.

If aubio_schmittS16LE does not hold onto the buf pointer then on the one hand we can say it does not take ownership and you can use whatever method you like to ensure buf is allocated - using AUBIO_MALLOC or  new [] or a std::vector<short>, or even a large fixed size automatic array with suitable runtime size checks (although allocating large amounts of data on function call stack frames is not necessarily a good idea). On the other hand your function would own the buffer resources and would have to ensure this memory was released by AUBIO_FREE or delete []; std::vector<short> and automatically allocated arrays will do so automatically.

So I would write your function in one of two ways:

1/ If aubio_schmittS16LE takes ownership of the buffer resources it is passed (and may hold onto it for use after returning) then I would do something like the following: (I reduce "signed short int" to "short" for brevity):


   smpl_t aubio_pitchschmitt_detect( aubio_pitchschmitt_t *p, fvec_t * input )
   {
   // Allocate buffer using AUBIO_MALLOC - or other AUBIO specific method
   // as indicated by aubio_schmittS16LE or related documentation.
       short * buf = reinterpret_cast<short>( AUBIO_MALLOC(input->length*sizeof(short)) );
       
  // Add check that you actually got the buffer memory and take appropriate action if not
    
       uint_t i;
       for (i=0; i<input->length; i++)
       {
         buf[i] = input->data[0][i]*32768;
       }

   // aubio_schmittS16LE is responsible for releasing the buffer memory
       return aubio_schmittS16LE(p, input->length, buf);
   }

Note that I have elided error checking, just added a comment where it should be done.

2/ If aubio_schmittS16LE does not take ownership nor holds onto the buf pointer the I would likely do something as similar to the following:

   #include <vector>
   
   // ...
   
   smpl_t aubio_pitchschmitt_detect( aubio_pitchschmitt_t *p, fvec_t * input )
   {
   // Create a std::vector<short> holding input->length elements initialised to 32768
       std::vector<short> buf(input->length, 32768);
       for (uint_t i=0; i<input->length; i++)
       {
         buf[i] *= input->data[0][i];
       }

   // aubio_schmittS16LE does not hold onto nor takes ownership of buffer resources
   // Note we use the take address of zeroth element idiom to gain access to internal
   // array memory that can be used as a C array.
       return aubio_schmittS16LE(p, buf.size(), &buf[0]);
   }
   // buf is a std::vector type which will be destroyed here and in
   // doing so destroys its elements and releases their memory.

Notice that my second solution uses modern (i.e. 1998 ISO standard) C++ idioms. It makes use of the C++ library vector class template to hold values in a (re-sizeable) contiguous block. The good thing about std::vector types is that they allow us to have the ease of use of a local object together with the dynamic properties of a dynamically allocated array. It is less elegant to initialise than an automatic or static array as we cannot use an initialiser list to initialise its elements ( as in: int array[] = { 1, 2, 3, 4 }; ) - ho hum. On the plus side for this case we have a useful constructor that allows us to specify how many elements we want and what their initial value will be - I choose to use this to preset all values to your magic 32768 value (which you specify as a double by leaving a trailing .)  so we can then just use *= to multiply them by the input data value. The alternative would be to create the elements with the default constructed value for a short (which is zero) only to have it immediately overwritten! Another possibility is to initially have no elements at all and create new ones as we go:

       std::vector<short> buf; // buf has no elements to start
       for (uint_t i=0; i<input->length; i++)
       {
         buf.push_back( input->data[0][i]*32768 );
       }

However note in this case that buf may end up using more memory than strictly required as vector implementations typically allocate and re-allocate memory in increasing chunk sizes as they grow to reduce the overhead or reallocating memory and copying elements. Typical growth rates are *2 and *1.5 times the current (too small) size. We could get around this by reserving the exact number of elements first:

       std::vector<short> buf; // buf has no elements to start
       buf.reserve( input->length );
       // ...

This reserves the raw storage but does not initialise or even create the elements so we still need to create elements by calling push_back.

Note that if buf cannot get the required memory then it will throw a std::bad_alloc exception.

I also use C++ syntax that allows defining and initialising variables in for statements.

Now a bit on your use of 32768. Note that literal values such as 32768 are so called magic numbers. 32768 obviously has some meaning here but to me as a reader of your code who does not know the requirements its meaning is magic - it is so to make it work! It is good practice to name such values:

   int const AubioDataMultiplier( 32768 );

   // ...

Of course the name I have chosen is just an example - it is somewhat vague due to my lack of familiarity with the problem and solution domains. Note that I am using an int as for typical 32-bit compilers 32768 will fit into a signed int of 32-bits but not a signed short int of 16 bits (note: this bit pattern will for 2 complement signed 16-bit values represent -32768). I do not know then if this value is correct. You may well get warnings from the compiler about loss of data or similar - which is quite probably as all results of 2s compliment 16 bit values  when multiplied by 32768 be zero or have zeros in the 15 least significant bits. Thus the only values produced will be 0 or -32768. Here is a throwaway program to illustrate this point (built with Microsoft Visual C++ 2008 - yes I actually tried this chunk of code<g>!):

   #include <iostream>
   #include <iomanip>
   #include <limits>

   using namespace std;

   int main()
   {
     int const AubioDataMultiplier( 32768 );

     bool tostart(true);
     for ( short i=std::numeric_limits<short>::min()
         ; tostart || i!=std::numeric_limits<short>::min()
         ; ++i
         )
       {
         tostart = false;
         std::cout << std::setw(6) << std::setfill(' ') << i << ":"
         << std::setw(6) << std::setfill('0')
         << static_cast<short>(i*AubioDataMultiplier)
         << " ## "
         ;
         if ( 0==i%4 )
         {
         std::cout << std::endl;
         }
       }
   }

For a 16-bit short it prints all 65536 values with the result of multiplying them by the AubioDataMultiplier values, cast back to a short, four pairs per line.

Given this I am not really sure this is what you were after. Although seeing references to Schmitt (as in Schmitt trigger I presume for squaring up waveforms/transitions) it may be.

Hope this helps.

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.