I have this piece of code in a function. I want to print the value of y
here.
if (x1 < 0 || y1 < 0) {
// Vertical lign outside of layer
if (dx == 0 && y1 < 0) {
return GKIT_NOERR;
}
float m = dy / dx;
float t = y1 - m * x1;
float x = -t / m;
float y = m * x + t;
printf("Hello %s. You are %f years old.\n", "Niklas", y);
}
But I get a segmentation fault. It works with no value at all to be printed as float. I can change that to %d
or similar, which works fine.
int val = (int) y;
printf("Hello %s. You are %d years old.\n", "Niklas", val);
Any idea where the Segfault comes from?
Edit : Complete function.
// coding: ascii
// author: Niklas Rosenstein
// e-mail: rosensteinniklas@googlemail.com
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gkit/defines.h"
#include "gkit/utils.h"
#include "gkit/graphicslayer.h"
#define SWAP_IF_NECCESSARY(x1, y1, x2, y2) \
if (x2 < x1 && y2 < y1) { \
int temp = x2; \
x2 = x1; \
x1 = temp; \
temp = y2; \
y2 = y1; \
y1 = temp; \
}
/* Based on Bresenhams line algorithm. */
int gk_GraphicsLayer_drawLine(gk_GraphicsLayer* layer, gk_Color* color,
int x1, int y1, int x2, int y2,
gk_ColorBlendProc blend, gk_float opacity) {
SWAP_IF_NECCESSARY(x1, y1, x2, y2);
float dx = x2 - x1;
float dy = y2 - y1;
float cx = x1;
float cy = y1;
// Figure out where to start in case x1 or y1 are outside of the layer.
if (x1 < 0 || y1 < 0) {
// Vertical lign outside of layer
if (dx == 0 && y1 < 0) {
return GKIT_NOERR;
}
// The function's slope (m)
// ------------------------
float m = dy / dx;
// Find the y-axis intersection (t)
// -------------------------------
// y = mx + t =>
// y - mx = t
float t = y1 - m * x1;
// Compute the root of the function (N)
// ------------------------------------
// 0 = mx + t =>
// mx = -t =>
// x = -t / m
float x = -t / m;
float y = m * x + t;
printf("Hello %s. You are %f years old.\n", "Niklas", y);
}
int incx = GKIT_SIGNUM(dx);
int incy = GKIT_SIGNUM(dy);
if (dx < 0) { dx = -dx; }
if (dy < 0) { dy = -dy; }
int pdx, pdy;
int ddx, ddy;
int es, el;
ddx = incx;
ddy = incy;
if (dx > dy) {
pdx = incx;
pdy = 0;
es = dy;
el = dx;
}
else {
pdx = 0;
pdy = incy;
es = dx;
el = dy;
}
float err = el / 2.0;
#define SET_PIXEL(x, y) \
do { \
gk_Color* c = GKIT_GRAPHICSLAYER_ACCESSPIXEL(layer, (int)x, (int)y); \
if (blend != Null) { \
gk_Color t = *c; \
blend(color, &t, c, opacity); \
} \
else { \
*c = *color; \
} } while (0)
SET_PIXEL(cx, cy);
int t;
for (t=0; t < el; t++) {
err -= es;
if (err < 0) {
err += el;
cx += ddx;
cy += ddy;
}
else {
cx += pdx;
cy += pdy;
}
SET_PIXEL(cx, cy);
}
#undef SET_PIXEL
return GKIT_NOERR;
}
Edit : Complete stack trace:
#0 0xb7e68cb0 ___printf_fp(fp=0xb7fc3a20, info=0xbffff684, args=0xbffff6f8) (printf_fp.c:844)
#1 0xb7e63ab0 _IO_vfprintf_internal(s=0xb7fc3a20, format=<optimized out>, ap=0xbffff750 "\001") (vfprintf.c:1623)
#2 0xb7e6cc2f __printf(format=0x8049da0 "Hello %s. You are %f years old.\n") (printf.c:35)
#3 0x8049143 gk_GraphicsLayer_drawLine(layer=0x804d008, color=0xbffff810, x1=-20, y1=-10, x2=49, y2=200, blend=0, opacity=0) (/home/niklas/git/c-gkit/gkit/graphicslayer.c:180)
#4 0x8049ba4 test_drawLine() (/home/niklas/git/c-gkit/main.c:46)
#5 0x8049c80 main() (/home/niklas/git/c-gkit/main.c:68)
Edit : Please note that printf()
does work when putting it after or before the if-clause. Ie Something like
printf("Foo: %f\n", 1.0);
// Figure out where to start in case x1 or y1 are outside of the layer.
if (x1 < 0 || y1 < 0) {
// Vertical lign outside of layer
if (dx == 0 && y1 < 0) {
return GKIT_NOERR;
}
does work , but moving the printf()
inside the if-clause yields a segmentation fault.
Update : According to TED 's answer, I've tested around a little and this is what came out:
The problem seem the be the outcome of the comparison operations ( <
). I can do
if (True) { printf("%f", 53.3); }
but I can't do
if (x1 < 0 || y1 < 0) { printf("%f", 53.3); }
// nor
if (x1 < 0) { printf("%f", 53.3); }
// nor
int x_smaller = x1 < 0;
if (x_smaller) { printf("%f", 53.3); }
Interesting is, that this works:
int x_smaller = x1 < 0;
int y_smaller = y1 < 0;
x_smaller = y_smaller = 1;
if (x_smaller || y_smaller) { printf("%f", 53.3); }
Conclusion : The outcome of the operations x1 < 0
and y1 < 0
tested in the if-clause make printf()
fail. The questions are:
If you are interested in the whole code, I don't mind sharing it. It's on github . It's a Code::Blocks project. The only include-path must be to the parent-directory of the gkit
folder.
This is exactly why I hate printf()
. It is about the most error-prone routine in an otherwise error-prone language.
The first thing to do with a "werid" crash is to simplify the logic to try to narrow it down.
In this case, I'd next try setting your float to a known value (eg: 1.0
) right before the printf
. It could be that your printf
has a bug on some weird value that you happen to have in there.
If that works (prints 1.0
) then my next step would be to try to print the bits in that variable. For C, that would probably be changing the format to %x
and the parameter to something like *((unsigned int *)(&y))
If it didn't work (I'm guessing not from your comment) keep simplifying. Try removing the %s
and its parameter (kind of unnessecary ATM anyway). If that still fails, either try:
Thanks to unkulunkulu, who provided his help in the chat , we were able to find the issue.
I couldn't believe that previous calls to gk_GraphicsLayer_drawLine
could influence the behaviour of following calls, but exactly this was the case. In my main()
function, I called the function three times. The first call recieved accidently values that did also reach out of bounds of the pixel-array of gk_GraphicsLayer
. The third call was the one who finally crashed the program.
This also explains why exiting the function after the if-clause (where the error appeared in) fixed the segfault. It was because it prevented the function from accessing memory it shouldn't access.
Summary : Writing to the memory of an invalid address is so much dangerous, it can even trigger a completely other function to fail and lead you to miss-asumptions. Unfortunately, one doesn't recieve Segmentation Fault errors when the invalid address is still in range of the memory that was supplied by the OS for your application.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.