LinuxQuestions.org
Did you know LQ has a Linux Hardware Compatibility List?
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 01-08-2008, 08:43 PM   #1
violagirl23
Member
 
Registered: Aug 2007
Location: Michigan
Distribution: Gentoo, Arch
Posts: 33

Rep: Reputation: 15
Simple C++ Program: Program Compiles But Won't Run (Segmentation Fault)


I have been trying to teach myself C++ lately (because it's so fun to program!) but I'll admit that I'm still a rotten shame at it. I've been trying to use pointers, and my friend who is a professional programmer told me that to edit a variable in a function not declared in that function, I'd have to use pointers, pass the pointer to the function (or something like that, I hope I didn't misunderstand him!)
This is the example he gave:
Code:
int bar( int *ptr )
{
 *ptr += 30;
}

int foo()
{ 
 int x = 7;
 int *x_ptr = &x;
 bar( x_ptr );
 cout << x << endl;
}
I have lately been trying to figure out how to make a function that will do prime factorization for me, like breaking 500 down to 2x2x5x5x5. I've figured out that I need to use vectors and I'm going to change my method of testing if the factor can't be divided anymore (I'm using floats and testing if the float equals the int of that variable) and just going to use ints with a different method.
HOWEVER, I want to fix OTHER issues before this. One thing at a time, right?
Right now I have a function blah();, right? (Yes, I had fun naming these XD). I am currently just calling blah(); from int main() just to test this particular piece of code and this will later become a header file for another file, hopefully. So anyway, I have a function, called repeat(), that does all the work for me. However, I have to do a FEW things before I use repeat();, so I made another function, blah(), as I mentioned, where I do these few things and then call repeat(); Repeat then goes on to do its thing and use lots of recursion to solve my factorization for me and print it to screen.
Great.
Problem is that the program compiles fine, but when I try to run it, I get "Segmentation Fault."
Does this mean there is something wrong with my pointers? It seems a little excessive to me to have to declare two sets of pointers for my variables just to use them (they are not declared themselves in repeat(), so without the pointers I get compile errors about scope. But I'm not sure how else to do it.
So thus I have TWO questions.
a: Can anybody figure out where the segmentation fault is? I looked the code over several times and still can't find a single thing wrong, though obviously there is SOMETHING wrong or it'd be working!
and b: Is there any other better way to do this, this being modifying these variables in repeat() without having to use this many pointers to do it? It just seems so excessive, like there must be a better way and I'm just overcomplicating things.
Here is the code:
Code:
#include <iostream>

using namespace std;

int blah();
void repeat(int *p_Count,float *p_Number,int *p_Divisor);

int main()
{
    blah();
    return 0;
}

int blah()
{
    int count = 0; // ignore for now
    float number = 0; //number to be factored
    int divisor = 2;
    /* ^^^^^^^^ This will increase by 1 everytime it can't factor it down. 
    So for example, it will keep dividing the number by 2 until it is not 
    evenly divisible anymore and then will move onto three, etc. */
    int *p_count = &count;  //some pointers to pass the variables later
    float *p_number = &number;
    int *p_divisor = &divisor;
    cout << "What is the number you want to factor?\n";
    cin >> number;
    cin.ignore();
    repeat(p_count,p_number,p_divisor);
    cin.get();
    return 0;
}

void repeat(int *p_Count,float *p_Number,int *p_Divisor)
{
    *p_Number = (*p_Number / *p_Divisor);
	
    /* check if dividing by divisor made a decimal or if the number's
    all the way down to 1 */
    if ( *p_Number==int(*p_Number) && *p_Number !=1 ) 
    { 
        cout << *p_Divisor << "x";
        repeat(p_Count,p_Number,p_Divisor);
    }
    else if (*p_Number == 1)
    {
        cout << *p_Divisor; // we're all done!
    }
    else
    {
        *p_Number *= *p_Divisor; // get back to before we had decimal
	*p_Divisor++; // add one to the divisor and start testing again!
	repeat(p_Count,p_Number,p_Divisor);
    }
}
It seems to work in MY mind at least. Someone would put in 500, then 500 would be divided by 2, it would check if it is still an integer, if so, it divides by 2 again, until it is no longer an integer (meaning it's not a factor, obviously).
Then it fails the test, goes to the else, multiplies the number by the divisor so it is back where it started BEFORE it got divided and become a decimal, then adds one to the divisor and starts again with a divisor one higher, say 3, and tries the tests again. It fails with three, goes to four, fails again, then goes to five and succeeds, three times in fact. The last time, when it gets it down to one, the else if is what will end it.
I ran through it with numbers in my mind and it SEEMED logical enough, but I obviously have errors in my code somewhere, because it won't run because of a "Segmentation Fault." Can anybody point out where my problem is? ^_^
Thanks!

Last edited by violagirl23; 01-08-2008 at 09:06 PM.
 
Old 01-08-2008, 10:26 PM   #2
cram869
LQ Newbie
 
Registered: Aug 2004
Location: Poughkeepsie, NY
Distribution: Fedora, RHEL, Slackware, Gentoo, KnoppMyth
Posts: 22

Rep: Reputation: 0
The code you posted has a few lines in it that can behave unpredictably. I would actually suggest that you change your algorithm, but this code would fail in any case. It took me a few minutes to realize what was happening. The major issue occurs when you increment your p_Divisor in the repeat() function. The line
Code:
*p_Divisor++;
first causes the pointer p_Divisor to be incremented, changing the address the pointer points to. Then, the "*" dereferences the pointer giving you whatever number exists at the next memory location. This is due to the order of operations between the increment operator "++" and the dereferencing operator "*". If you change any lines with those two operators to something like
Code:
(*p_Divisor)++;
you should be in better shape. When in doubt of the order of operations, I tend to throw the parenthesis for good measure. It also makes the code a little more readable in my opinion.

Since you are just playing with this code, maybe you don't care, but I would suggest you change your algorithm to something a little more robust. Dividing floats and then multiplying by previous divisor is just asking for a round off error. Then, you will have some value in your p_Number location like 5.000000001 that will never factor out. You could accomplish your goal with nothing but integers and integer operations. I would suggest removing the first division in repeat(). Then, in your first "if" statement replace your check with
Code:
if( (*p_Number) % (*p_Divisor) == 0 )
The "%" operator returns the integer remainder of *p_Number/(*p_Divisor) without resorting to floating point calculations. When you have no remainder, you have found a proper factor of the number. You will have to change other parts of the function to make this work for you, but it should be more robust.
 
Old 01-09-2008, 12:23 AM   #3
violagirl23
Member
 
Registered: Aug 2007
Location: Michigan
Distribution: Gentoo, Arch
Posts: 33

Original Poster
Rep: Reputation: 15
Well, I took your advice about using remainders instead of dividing floats. Thanks for the advice. =)
And thank you for helping with the pointer. It never even occurred to me that the * could be separated from the pointer in such operations. Whenever I type *pointer I just think of that so much as being one unit that I didn't realize you could separate it like that with such operations. Well, I sure know from now on!!!!!!!!
Through boredom and trial and error, I found that the highest number my program will factor to with integers is 2,147,483,367.
Hee hee.
I'm assuming that this has to do with how much data integers can store, correct?
If I wanted more precision, what is the most precise variable type? Double float? What was that again, if integer is int, then double float is... double?
If so, I'll probably just do a check if the number is larger than 2,147,483,367 do it with double... or maybe just do the whole thing in double. :-p
I suppose I'd have to devise a new test then......
% doesn't seem to work with double.
And I think taking the double variable and doing int(variable) wouldn't work either because integers CAN'T hold that much.
Now setting an int to one digit above the number I mentioned and then displaying it works.... so it seems ints can store more than this. So what might be the reason for my factoring program failing at this particular number? Just curious.

Edit: Actually, I started looking at some of the VALUES it's spitting and multiplying them... way off sometimes. I've still got some problems.
I'll start by doing a remainder test on my divisor to make positively sure it a prime factor.....
And then figure out where else it is going awry.

Last edited by violagirl23; 01-09-2008 at 12:34 AM.
 
Old 01-09-2008, 01:09 AM   #4
nc3b
Member
 
Registered: Aug 2005
Posts: 330

Rep: Reputation: 32
If you want to use an integer variable that is just bigger you could go along with unsigned int or long or unsigned long etc. Just check what your compiler thinks about it

Code:
cout<<sizeof(int)<<" "<<sizeof(long);
will show you what size a variables is.

And another thing. I really hate writing * so much, I would rather go with references.

Code:
void bar(int &ref)
{
	ref+=30;
}

int main()
{
	int x=7;
	bar(x);
	cout<<x<<endl;
}
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ Program, Segmentation Fault Fireball7 Programming 6 12-07-2005 05:22 PM
why segmentation fault in this program? asahlot Programming 13 10-17-2005 01:47 PM
gcc, segmentation fault, though compiles... scratch09 Programming 5 11-20-2004 06:11 PM
libxml++: segmentation fault when exiting program. isl01jbe Programming 0 06-20-2004 06:47 AM
"segmentation fault" when run a simple c program acer_peri Programming 11 05-28-2004 05:14 AM


All times are GMT -5. The time now is 11:34 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration