-- All of the revised code still refuses to run well, please help --
When I compile my code in Windows, I get memory errors. However on the Mac, where I initially coded this code, it works fine. I need to get this working on Windows.
It's something to do with the way I handle my char strings using strcpy that the Mac seems to be fine with (I guess it's related to gcc vs. Microsoft's way of doing things).
Here's the code for the complainers:
main.cpp
#include "Cust.h"
using namespace std;
int main (int argc, char * const argv[]) {
Cust customers[500];
char tmpString[70] = " ";
char * pch = new char[255];
string tmpAcctFN = " ";
string tmpAcctLN = " ";
ifstream input("P3_custData.txt");
for (int idx = 0; idx < 130; idx++){
input.getline(tmpString, 70, '\n');
strcpy(pch,strtok(tmpString," "),255);
customers[idx].setAcctNum(pch);
cout << pch << endl;
strcpy(pch, strtok(NULL," "));;
customers[idx].setAcctFN(pch);
cout << pch << endl;
strcpy(pch, strtok(NULL," "));;
customers[idx].setAcctLN(pch);
cout << pch << endl;
strcpy(pch, strtok(NULL," "));;
customers[idx].setCurrBalance(atol(pch));
cout << pch << endl;
strcpy(pch, strtok(NULL," "));;
customers[idx].setPIN(atoi(pch));
cout << pch << endl;
}
input.close();
return 0;
}
Cust.h
/*
* Cust.h
* Project 3
*
* Created by Anthony Glyadchenko on 11/17/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
*
*/
#include <iostream>
#include <string>
using namespace std;
#ifndef CUST_H
#define CUST_H
class Cust{
public:
char * getAcctNum();
void setAcctNum(char num[]);
double getCurrBalance();
void setCurrBalance(double balance);
void addToCurrBalance(double amount);
void subFromCurrBalance(double amount);
void setAcctFN(char firstName[]);
void setAcctLN(char lastName[]);
char * getAcctFN();
char * getAcctLN();
void setPIN(int pin);
int getPIN();
private:
char acctNum[255];
char acctFN[255];
char acctLN[255];
double currBalance;
int pin;
char fileName[255];
};
#endif
Cust.cpp
/*
* Cust.cpp
* Project 3
*
* Created by Anthony Glyadchenko on 11/17/09.
* Copyright 2009 __MyCompanyName__. All rights reserved.
*
*/
#include <fstream>
#include <string>
#include <sstream>
#include "Cust.h"
using namespace std;
char * Cust::getAcctNum(){
return acctNum;
}
void Cust::setAcctNum(char num[]){
strcpy(acctNum,num);
}
double Cust::getCurrBalance(){
return currBalance;
}
void Cust::setCurrBalance(double balance){
currBalance = balance;
}
void Cust::addToCurrBalance(double amount){
currBalance += amount;
}
void Cust::subFromCurrBalance(double amount){
currBalance -= amount;
}
void Cust::setAcctFN(char firstName[]){
strcpy(acctFN,firstName);
}
void Cust::setAcctLN(char lastName[]){
strcpy(acctLN,lastName);
}
char * Cust::getAcctFN(){
return acctFN;
}
char * Cust::getAcctLN(){
return acctLN;
}
void Cust::setPIN(int pin){
Cust::pin = pin;
}
int Cust::getPIN(){
return pin;
}
Here is my stack trace:
Index Function
--------------------------------------------------------------------------------
1 msvcr90d.dll!68d7f693()
2 [Frames below may be incorrect and/or missing, no symbols loaded for msvcr90d.dll]
*3 P3.exe!main(int argc=0, char * const * argv=0x0036fcd0)
4 P3.exe!_FreeLibrary#4()
5 P3.exe!#ILT+170(__except_handler4)()
6 kernel32.dll!75eb3677()
7 ntdll.dll!77b29d72()
8 ntdll.dll!77b29d45()
A few things to check (sorry not going to download the code):
does g++ *.c have warnings? If so fix them.
does g++ -W have warnings? If so fix them.
does g++ -W -Wall have warnings? If so fix them.
does g++ -W -Wall -Wextra have warnings? If so fix them.
does g++ -W -Wall -Wextra -ansi have warnings? If so fix them.
does g++ -W -Wall -Wextra -ansi -pedantic have warnings? If so fix them.
On microsoft try adding /W4 to the command line to turn the warning up, again fix any issues.
Odds are you are doing something "silly" and chances are that the compiler can help you catch what it is.
Edit:
From compiling your code with the flags above you will see:
Cust.h:33: error: ISO C++ forbids zero-size array ‘acctNum’
Cust.h:34: error: ISO C++ forbids zero-size array ‘acctFN’
Cust.h:35: error: ISO C++ forbids zero-size array ‘acctLN’
Cust.h:38: error: ISO C++ forbids zero-size array ‘fileName’
Cust.h:33: error: ISO C++ forbids zero-size array ‘acctNum’
Cust.h:34: error: ISO C++ forbids zero-size array ‘acctFN’
Cust.h:35: error: ISO C++ forbids zero-size array ‘acctLN’
Cust.h:38: error: ISO C++ forbids zero-size array ‘fileName’
So your code is not valid C++. You are copying a name into an array that is too small - the array has 0 elements. What you really need to do is give the arrays a size when you declare them or declare them as pointers and then use "new" to allocate the right amount of memroy.
Passing invalid buffers, buffers that are too small, etc., to strcpy results in undefined behavior - just about anything can happen. On the Mac, the problems happen but aren't apparent, while on Windows it results in a crash.
char acctNum[];
char acctFN[];
char acctLN[];
There's your problem right there. You never seem to allocate any space for these strings anywhere. The strcpy() in setAcctNum() is overflowing the bounds of that unsized array, and overwriting something else. It's pretty amazing that this compiles at all, actually.
You probably ought to be using std::string, instead - that'll make the memory management easier, at least.
Probably is your implementation of the strcpy function, which could have differences between how it is coded on the mac and how it's coded on Windows.
Related
1.FORTRAN source (main.for)
integer function mysum(a, b)
!DEC$ATTRIBUTES DLLEXPORT,STDCALL :: mysum
!DEC$ATTRIBUTES VALUE :: a, b
integer a,b
mysum = a + b
return
end function mysum
make dll
gfortran main.for -shared -o fordll.dll
call dll
#include <stdio.h>
#include <iostream>
#include <windows.h>
using namespace std;
typedef int(_stdcall * MYSUM)(int a, int b);
int main()
{
int a=10,b=20;
HINSTANCE hLibrary = LoadLibrary("fordll.dll");
if (hLibrary == NULL)
{
cout << "can't find the dll file" << endl;
return -1;
}
MYSUM fact = (MYSUM)GetProcAddress(hLibrary, "mysum");
if (fact == NULL)
{
cout << "can't find the function file." << endl;
return -2;
}
try
{
cout << fact(a,b);
}
catch(...)
{ }
FreeLibrary(hLibrary);
return 0;
}
ERROR
Exception Access Violation reading 0x0000000A
why? if the fortran source file is comppiled by Compad Visual fortran or Inter fortran, it works well. However, it doesn't work with gcc or gfortran. What's wrong?
You are using special directives to alter the calling conventions
!DEC$ATTRIBUTES DLLEXPORT,STDCALL :: mysum
!DEC$ATTRIBUTES VALUE :: a, b
However, these are only valid for the DEC compiler sand its descendant Intel Fortran.
GCC use !GCC$ directives instead. Use them, they are pretty much the same as the DEC ones. See https://gcc.gnu.org/onlinedocs/gfortran/ATTRIBUTES-directive.html#ATTRIBUTES-directive Just change coppy and paste the DEC directives and change DEC to GCC.
Alternatively, change the code to pass-by-reference and ditch the VALUE attribute. The STDCALL attribute is relevant for 32-bit Windows only.
In modern Fortran it is much better to use
integer function mysum(a, b) bind(C,name="mysum")
integer, value :: a, b
(ignoring the stdcall issue, which can be just deleted in the C++ code).
I have a strange segmentation fault that doesn't exist when everything is in 1 .c file, but does exist when I put part of the code in a dynamically linked library and link it to a test file. The complete code for the working 1 .c file code is at the bottom, the complete code for the error system with 2 .c and 1 .h file come first.
Here is the error system:
example.h:
#include <stdio.h>
#include <stdlib.h>
typedef struct MYARRAY {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypush(void* p);
example.c:
#include "example.h"
void
mypush(void* p) {
printf("Here %lu\n", sizeof collection);
puts("FOO");
int len = collection->len++;
puts("BAR");
collection->items[len] = p;
}
example2.c:
This is essentially a test file:
#include "example.h"
void
test_print() {
puts("Here1");
mypush("foo");
puts("Here2");
}
int
main() {
collection = malloc(sizeof *collection + (sizeof collection->items[0] * 1000));
collection->len = 0;
puts("Start");
test_print();
puts("Done");
return 0;
}
Makefile:
I link example to example2 here, and run:
example:
#clang -I . -dynamiclib \
-undefined dynamic_lookup \
-o example.dylib example.c
#clang example2.c example.dylib -o example2.o
#./example2.o
.PHONY: example
The output is:
$ make example
Start
Here1
Here 8
FOO
make: *** [example] Segmentation fault: 11
But it should show the full output of:
$ make example
Start
Here1
Here 8
FOO
BAR
Here2
Done
The weird thing is everything works if it is this system:
example.c:
#include <stdio.h>
#include <stdlib.h>
typedef struct MYARRAY {
int len;
void* items[];
} MYARRAY;
MYARRAY *collection;
void
mypush(void* p) {
printf("Here %lu\n", sizeof collection);
puts("FOO");
int len = collection->len++;
puts("BAR");
collection->items[len] = p;
}
void
test_print() {
puts("Here1");
mypush("foo");
puts("Here");
}
int
main() {
collection = malloc(sizeof *collection + (sizeof collection->items[0] * 1000));
collection->len = 0;
puts("ASF");
test_print();
return 0;
}
Makefile:
example:
#clang -o example example.c
#./example
.PHONY: example
Wondering why it's creating a segmentation fault when it is linked like this, and what I am doing wrong.
I have checked otool and with DYLD_PRINT_LIBRARIES=YES and it shows it is importing the dynamically linked libraries, but for some reason it's segmentation faulting when linked but works fine when it isn't linked.
Your problem is this, in example.h:
MYARRAY *collection;
Since both main.c and example.c include this file, you end up defining collection twice, which results in undefined behavior. You need to make sure you define each object only once. The details are relatively unimportant since anything can happen with undefined behavior, but what's probably happening is that main.c is allocating memory for one object, but the one example.c is using is still NULL. As mentioned in the comments, since you define collection in main.c your linker is able to build the executable without needing to look for that symbol in the dynamic library, so you don't get a link time warning about it being defined there too, and obviously there'd be no cause for a warning at the time you compile the library.
It works for you when you put everything in one file because obviously then you're not defining anything twice, anymore. The error itself is nothing to do with the fact you're using a dynamic library, although that may have made it harder to detect.
It would be better to define this in example.c and provide a constructor function, there's no need for main() to be able to access it directly. But if you must do this, then define it in example.c and just declare an extern identifier in the header file to tell main.c that the object is defined somewhere else.
I am trying to convert a c++ program I have which uses random library which is a C++11 feature. After having read through a couple of similar posts here, I tried by separating out the code into three files. At the outset I would like to say that I am not very conversant at C/C++ and mostly use R at work.
The main file looks as follows.
#ifndef _KERNEL_SUPPORT_
#define _KERNEL_SUPPORT_
#include <complex>
#include <random>
#include <iostream>
#include "my_code_header.h"
using namespace std;
std::default_random_engine generator;
std::normal_distribution<double> distribution(0.0,1.0);
const int rand_mat_length = 24561;
double rand_mat[rand_mat_length];// = {0};
void create_std_norm(){
for(int i = 0 ; i < rand_mat_length ; i++)
::rand_mat[i] = distribution(generator);
}
.
.
.
int main(void)
{
...
...
call_global();
return 0;
}
#endif
The header file looks as follows.
#ifndef mykernel_h
#define mykernel_h
void call_global();
void two_d_example(double *a, double *b, double *my_result, size_t length, size_t width);
#endif
And the .cu file looks like the following.
#ifndef _MY_KERNEL_
#define _MY_KERNEL_
#include <iostream>
#include "my_code_header.h"
#define TILE_WIDTH 8
using namespace std;
__global__ void two_d_example(double *a, double *b, double *my_result, size_t length, size_t width)
{
unsigned int row = blockIdx.y*blockDim.y + threadIdx.y;
unsigned int col = blockIdx.x*blockDim.x + threadIdx.x;
if ((row>length) || (col>width)) {
return;
}
...
}
void call_global()
{
const size_t imageLength = 528;
const size_t imageWidth = 528;
const dim3 threadsPerBlock(TILE_WIDTH,TILE_WIDTH);
const dim3 numBlocks(((imageLength) / threadsPerBlock.x), ((imageWidth) / threadsPerBlock.y));
double *d_a, *d_b, *mys ;
...
cudaMalloc((void**)&d_a, sizeof(double) * imageLength);
cudaMalloc((void**)&d_b, sizeof(double) * imageWidth);
cudaMalloc((void**)&mys, sizeof(double) * imageLength * imageWidth);
two_d_example<<<numBlocks,threadsPerBlock>>>(d_a, d_b, mys, imageLength, imageWidth);
...
cudaFree(d_a);
cudaFree(d_b);
}
#endif
Please note that the __global__ has been removed from .h since I was getting the following error owing to it being compiled by g++.
In file included from my_code_main.cpp:12:0:
my_code_header.h:5:1: error: ‘__global__’ does not name a type
When I compile the .cu file with nvcc it is all fine and generates a my_code_kernel.o. But since I am using C++11 in my .cpp I am trying to compile it with g++ and I am getting the following error.
/tmp/ccR2rXzf.o: In function `main':
my_code_main.cpp:(.text+0x1c4): undefined reference to `call_global()'
collect2: ld returned 1 exit status
I understand that this might not have to do anything with CUDA as such and may just be the wrong use of including the header at both places. Also what is the right way to compile and most importantly link the my_code_kernel.o and my_code_main.o(hopefully)? Sorry if this question is too trivial!
It looks like you are not linking with my_code_kernel.o. You have used -c for your nvcc command (causes it to compile but not link, i.e. generate the .o file), I'm going to guess that you're not using -c with your g++ command, in which case you need to add my_code_kernel.o to the list of inputs as well as the .cpp file.
The separation you are trying to achieve is completely possible, it just looks like your not linking properly. If you still have problems, add the compilation commands to your question.
FYI: You don't need to declare two_d_example() in your header file, it is only used within your .cu file (from call_global()).
I'm aware of this SO question and this SO question. The element
of novelty in this one is in its focus on Xcode, and in its use of
square brackets to dereference a pointer to void.
The following program compiles with no warning in Xcode 4.5.2, compiles
with a warning on GCC 4.2 and, even though I don't have Visual Studio
right now, I remember that it would consider this a compiler
error, and MSDN and Internet agree.
#include <stdio.h>
int main(int argc, const char * argv[])
{
int x = 24;
void *xPtr = &x;
int *xPtr2 = (int *)&xPtr[1];
printf("%p %p\n", xPtr, xPtr2);
}
If I change the third line of the body of main to:
int *xPtr2 = (int *)(xPtr + 1);
It compiles with no warnings on both GCC and Xcode.
I would like to know how can I turn this silence into warnings or errors, on
GDB and especially Xcode/LLVM, including the fact that function main is int but
does not explicitly return any value (By the way I think -Wall does
the trick on GDB).
that isnt wrong at all...
the compiler doesnt know how big the pointer is ... a void[] ~~ void*
thats why char* used as strings need to be \0-terminated
you cannot turn on a warning for that as it isnt possible to determine a 'size of memory pointer to by a pointer' at compile time
void *v = nil;
*v[1] = 0 //invalid
void *v = malloc(sizeof(int)*2);
*v[1] = 0 //valid
*note typed inline on SO -- sorry for any non-working code
I'm having a really hard time getting an R library installed that requires some compilation in C. I'm using a Mac OSX Snow Leopard machine and trying to install this R package (here).
I've looked at the thread talking about getline on macs and have tried a few of these fixes, but nothing is working! I'm a newbie and don't know any C, so that may be why! Can anyone give me some tips on how I could modify files in this package to get it to install?? Anyhelp would be pathetically appreciated! Here's the error I'm getting:
** libs
** arch - i386
g++ -arch i386 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/i386 -I/usr/local/include -D_FASTMAP -DMAQ_LONGREADS -fPIC -g -O2 -c bed2vector.C -o bed2vector.o
In file included from /usr/include/c++/4.2.1/backward/strstream:51,
from bed2vector.C:8:
/usr/include/c++/4.2.1/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
bed2vector.C: In function ‘int get_a_line(FILE*, BZFILE*, int, std::string&)’:
bed2vector.C:74: error: no matching function for call to ‘getline(char**, size_t*, FILE*&)’
make: *** [bed2vector.o] Error 1
chmod: /Library/Frameworks/R.framework/Resources/library/spp/libs/i386/*: No such file or directory
ERROR: compilation failed for package 'spp'
The easiest solution is probably to add a static definition for getline() to bed2vector.c. This might be good enough:
/* PASTE AT TOP OF FILE */
#include <stdio.h> /* flockfile, getc_unlocked, funlockfile */
#include <stdlib.h> /* malloc, realloc */
#include <errno.h> /* errno */
#include <unistd.h> /* ssize_t */
extern "C" ssize_t getline(char **lineptr, size_t *n, FILE *stream);
/* PASTE REMAINDER AT BOTTOM OF FILE */
ssize_t
getline(char **linep, size_t *np, FILE *stream)
{
char *p = NULL;
size_t i = 0;
if (!linep || !np) {
errno = EINVAL;
return -1;
}
if (!(*linep) || !(*np)) {
*np = 120;
*linep = (char *)malloc(*np);
if (!(*linep)) {
return -1;
}
}
flockfile(stream);
p = *linep;
for (int ch = 0; (ch = getc_unlocked(stream)) != EOF;) {
if (i > *np) {
/* Grow *linep. */
size_t m = *np * 2;
char *s = (char *)realloc(*linep, m);
if (!s) {
int error = errno;
funlockfile(stream);
errno = error;
return -1;
}
*linep = s;
*np = m;
}
p[i] = ch;
if ('\n' == ch) break;
i += 1;
}
funlockfile(stream);
/* Null-terminate the string. */
if (i > *np) {
/* Grow *linep. */
size_t m = *np * 2;
char *s = (char *)realloc(*linep, m);
if (!s) {
return -1;
}
*linep = s;
*np = m;
}
p[i + 1] = '\0';
return ((i > 0)? i : -1);
}
This doesn't handle the case where the line is longer than the maximum value that ssize_t can represent. If you run into that case, you've likely got other problems.
Zeroth question: Have you considered using a package manager like fink or MacPorts rather than compiling yourself? I know that fink has an R package.
First question: How is the R build managed? Is there a ./configure? If so have you looked at the options to it? Does it use make? Scons? Some other dependency manager?
Second question: Have you told the build system that you are working on a Mac? Can you specify that you don't have a libc with native getline?
If the build system doesn't support Mac OS---but I image that R's does---you are probably going to have to download the standalone version, and hack the build to include it. How exactly you do that depends on the build system. And you may need to hack the source some.