Git’s like an undo button, but with labels showing you what changes were made when and with a history that goes back to the very first change you ever made to the project.
Git makes it easy to have different versions of the same document, to easily work by yourself on the same project on multiple computers, and to collaborate with other people (whether you’re working at different times or simultaneously!)
Git is software that you can install and run locally on your own computer. GitHub provides the service of storing and sharing your git repos online. Anyone can get a free account on GitHub and they provide free premium accounts to students (see here).
“Repo” is short for “repository”– repo is like a folder with files in it (that are usually related as part of a project), with an associated history of changes over time (“commits”).
A commit is a snapshot of your project at a certain point in time. Each commit has an author, a time, a unique long ID (also called a ‘SHA’ or ‘hash’), and a message describing what change it makes.
In this tutorial we’ll be working in Terminal.
(Windows users, open GitBash for the rest of the tutorial; Mac users, open Terminal.)
In terminal, type:
git --version
to see the current version of git that is installed.
Mac troubleshooting try installing: git version <IP_ADDRESS>
You can install the GitHub desktop app if you’d like a simple point-and-click experience. Or SourceTree (free), Tower (not free, but powerful and ~$25 with a student discount). It’s also possible to set up a git pane in RStudio.
Every Git commit uses this information. Type:
git config --global user.name "John Doe"
git config --global user.email<EMAIL_ADDRESS>Also run this once (it ensures that git pushes in a sane manner):
git config --global push.default simple
Make an account on GitHub: https://github.com/.
Create a new empty public repository at https://github.com/new
Call it ‘hello’ and make sure the “Add a README file” checkbox is checked1 For future reference (feel free to ignore this!): you can also turn any directory that’s already on your computer into a git repo by going to that directory using cd
and then typing git init
. Later, when you want to put the repo on GitHub, you go through the steps to make a new repo without initializing with a readme, then from your directory on your computer type the following (replacing the red text):.
git remote add origin git@github.com:your_user_name/repo_name.git
git push -u origin main
Then click the green ‘Code’ button to get the HTTPS URL:
Go back to Terminal (or GitBash).
Now we’ll clone the hello folder to your computer. For the purposes of this tutorial, let’s clone the folder to your desktop.
First use cd
and ls
to navigate to your desktop. (Mac users can type cd ~/Desktop
to get there.)
Then type (replacing the URL with the one you copied above):
git clone https://github.com/[username]/hello.git
At this point, if you are using a new GitHub account, you will most likely be prompted to authenticate to GitHub. There are a few ways to do this, depending on how you are accessing GitHub (all the options are outlined in more detail here, including instructions for GitHub Desktop), but we think the easiest way is to create a personal access token (PAT) to use in place of a password. To do this, follow the directions outlined here.
Once you generate a PAT, try the command again:
git clone https://github.com/[username]/hello.git
If prompted, enter your GitHub username and newly generated PAT in the place of your password2 If you would like a credential helper to help you store the PAT, follow instructions here based on your operation system. Now you should have a cloned copy of the empty repo on your Desktop.
A README file contains information about other files in a directory, and it’s customary to include one in your git repo. Your README will be rendered from markdown on the front page of your GitHub repository (see here and here for an example).
When you initialized your repo on GitHub, the site created an empty README file. Let’s write something in it.
Open the README file in a text editor3 There will be lots of files that are simple text files, with .md, .rmd etc. as filetypes. You can open all these with a text editor. Although your computer comes with a default one (e.g. Notepad, TextEdit), we would recommend downloading Sublime Text, which is free and has a lot of powerful tools that will be helpful in the future. and write a sentence or two describing your repo, and save your changes. (Read the basics of markdown and use it appropriately in formatting your README.)

Now we will add this file and commit it4 For future reference (feel free to ignore this!): you can add just part of the file by using git add -p README.md
and following the instructions at the bottom of the terminal window. so that git takes a snapshot of the changes we made:
git add README.md
git commit -m "update readme"
(-m
precedes a commit message, which allows you to describe what you changed.)
If you now type:
git status
You’ll get a message telling you that everything is up to date (“nothing to commit, working tree clean”).
Use RStudio5 We’ll be using R and RStudio in the future. If you do not yet have those downloaded, you can open up a text editor and do the same thing. to make a new R script containing one line, e.g., print("hello world")
. Save this as ‘pset0.R’ inside the hello folder.
Then, back in the terminal, type:
git status
This will tell you that a file called pset0.R exists, but isn’t being tracked by git.6 If you find a file called “.DS_Store” that is being tracked, that is a mac file saving folder preferences. You can add this to a .gitignore file as described in step 7 below so that git will not track it.
Now we will add this file and commit it (so that git starts to track it):
git add -A
(the -A
specifies that we will add all of the files that have been changed in the repo)
git commit -m "initial commit of pset0.R"
What we’ve done so far – add
and commit
– only affects your local computer. To get your changes on GitHub, use push
:
git push
If you go to your GitHub account, you can now see the updated files.
Now make some changes to your pset0.R file (delete and/or add another line or two of code) and save it.
In terminal, type
git status
to see that pset0.R has been modified since the last commit.
To see the specific changes since the last commit, type:
git diff
Then commit:
git add -A
git commit -m "[describe change]"
Push to the repository on GitHub:
git push
TIP: Commits should be focused. Try to commit little bite-sized changes that are all related to each other together and easy to label, and make separate commits for other changes.
Best practice for commit messages is to make sure your commit message is not too long and would fit into the sentence: “When you pull this commit, it will ______.”
Sometimes you will want to go back to a previous commit. Here’s how to do it:
To view previous commits, type:
git log
To change the number of displayed commits, type the number you want to see preceded by a dash. For example, to view the three most recent commits, type:
git log -3
(You can also view the commit history on GitHub.)
You can use the long ID numbers attached to commits (also called hashes or SHAs) to roll back to them if you need to see a previous version of the repo. This can be very useful if something breaks and you don’t know how that happened. You can roll back to the last commit where your program wasn’t broken and see what files changed since then, and how.
For example, let’s say we wanted to roll back to the very first commit so we could run the code as it was back then. Let’s look at the very first commit. You can find it by typing git log
and then pressing the space bar to scroll down to the very first commit. Copy and paste the hash for this commit, (press ‘q’ to get back to the main terminal window), and then type (replacing the hash with the one you copied):
git checkout a240f92a22cb8e9b1300bfa690e99ef07692151e
or just
git checkout a240f92
(Git is smart enough to figure out what commit you meant to type if you provide the first 8-10 characters of the hash.)
If you open up the hello folder on your desktop, you’ll notice that it’s now in the state it was after you made your first commit.
IMPORTANT WARNING: After you’ve finished inspecting a checkout, make sure you get back to where you started [the latest commit on the main branch] by typing:
git checkout main
To revert your files to the state they were in in an earlier commit, type (replacing 0766c053
with the first 8-10 characters of the hash you copied):
git revert --no-commit 0766c053..HEAD
git commit -m "revert all changes since first commit"
This will essentially take all of the changes you made since this commit, undo them, and then save this as a new commit. (Your prior commits will still exist.)
For more info on undoing things in git, check: https://github.com/blog/2019-how-to-undo-almost-anything-with-git
If you’d like to revert one specific commit (rather than all of the commits after a specific commit), type:
git revert --no-commit 0766c053
git commit -m "revert the commit where I did xyz..."
There are some things you don’t want on git:
output files (files that are deterministically generated by other files in the repo, e.g. generated PDFs in a LaTeX project repo)
log files (like .RData and .Rhistory. You can’t describe what “changes” were made to them and different people’s .RData and .Rhistory files will always conflict.)
sensitive data (like human subject data and passwords)
configuration files that have configurations specific to your computer (Important: If you are running stuff on Mechanical Turk, make sure your bin/mturk.properties file is NOT on git, because that file contains an access key to allow you to authenticate with Amazon.)
You can put these in a special .gitignore file so git won’t suggest you add them and will even remind you not to add them if you try to. You can create this .gitignore file in a text editor like Sublime Text and update as needed.
Your .gitignore file might look like this (saved exactly as “.gitignore” without a file extension):
# R created files
*.Rproj
*.Rproj.user
*.Rhistory
*.Ruserdata
*.history
*.RData
# Image/output files unless otherwise specified
*.png
*.docx
*.doc
*.jpg
*.gif
# Misc Knit Files
*.aux
*.gz
*.log
*.rdx
*.rdb
*.knit.md
*cache
*.results
# Other
*.httr-oauth
*.DS_Store
# MTurk credentials and data
auth.json-own-auth.json
my/
mturk-and-gmail.txt
mturk
# Specific file keep
!README.md
!/original....pdf
.Rproj.user
GitHub has many useful guides for learning about branches, pull requests, forking and more: https://guides.github.com/ https://help.github.com/articles/good-resources-for-learning-git-and-github/
Though the things we covered in this tutorial may seem overwhelming, there are really only a handful of commands that you need to know, which can be found (alongside some commands we didn’t cover) on this handy cheatsheet.
Request a premium account at https://education.github.com/ for free private repos.
To save some time, tell git to remember your GitHub username and password: https://help.github.com/articles/caching-your-github-password-in-git/
Or set up an SSH key to log in less often: https://help.github.com/articles/generating-ssh-keys
For Windows:
you need this code:
eval ssh-agent -s
ssh-add
and you need to run this part in GitBash
For students seeking deeper Git knowledge, ProGit is a thorough open source book from Scott Chacon. It can be viewed online or downloaded in ePub, Mobi, or PDF formats.
Acknowledgments: Thank you to Cayce Hook, Erin Bennett and Daniel Watson for creating the first version of this tutorial for Psych 251!


Hello! I'm John, a UX Developer who loves to
visualize
design
develop
visualize
cook-up
design
develop
visualize
design
develop
beautiful
functional
intuitive
scrumptious
beautiful
functional
intuitive
beautiful
functional
intuitive
experiences
architectures
solutions
tidbits
experiences
architectures
solutions
experiences
solutions
architectures


| year | wikipedia page | host | beginning | ending | teams | champions | second place | third place | fourth place | match count | goal count | attendance | venues |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| year | wikipedia page | host | beginning | ending | teams | champions | second place | third place | fourth place | match count | goal count | attendance | venues |


正常方案
I have a nice subtle inner rounding, don't I look pretty?
outline 方案
I have a nice subtle inner rounding, don't I look pretty?


Flattens a cell array of regular arrays into a regular array. Each element of X must be a regular array, and must have the same number of dimensions k. Converts X to an array Y of dimension k+1 where Y(:,:...,:,i) is X{i} padded to be as big as the biggest element in X (along each dimension). Specifically, let di1..dik be the k dimensions of element X{i}. Let dj=max(dij) for each j. Then each element of X{i} is padded to have size [d1 ... dk], and then the elements of X are stacked into a vector. Treats the cell array X as a vector (so ignores the layout of X). USAGE Y = cell2array( X, [padEl] ) INPUTS X - cell array of regular arrays each with dimension k padEl - [0] element with which to pad OUTPUTS Y - resulting array of dimension k+1 EXAMPLE for i=1:10; X{i}=rand(30); end; Y = cell2array(X); See also MAT2CELL2, CELL2MAT Piotr's Computer Vision Matlab Toolbox Version 2.40 Copyright 2014 Piotr Dollar. [pdollar-at-gmail.com] Licensed under the Simplified BSD License [see external/bsd.txt]


Access denied
You are not loged in or you do not have permission to access this page!
Login to access the page
Generate development token


dispatch_1.ws3
# register the websh command "pricelist"
web::command pricelist {
# web::put sends string to the default output channel
# (stdout in the CGI case), including HTTP headers
web::put {<tt>
price list
</tt>}
# web::cmdurl produces a URL with querystring. In this case,
# we just want to switch back to "default", that's why we omit
# an explicit command name and just use ""
web::put "back"
}
# register the websh command "default"
web::command default {
# welcome note
web::put {<tt>
hello, customer
</tt>}
# link to an other HTML page of this application, the price list.
# We generate the URL using web::cmdurl and specify the command
# to be used: it is called pricelist and has been defined above.
web::put "price list"
}
# do the command dispatching
# this will switch into "pricelist" or "default" depending on
# the query_string
web::dispatch
Generated by GNU enscript 1.6.3.


You are viewing an historical archive of past issues. Please report new issues to the appropriate project issue tracker on GitHub.
Comments
-
Greg Hurrell
Bah, just tried again, and now I am correctly getting a "fat" 32/64-bit extension.
Will have to mark this as closed.
-
Greg Hurrell
Status changed:
- From: new
- To: closed
-
Greg Hurrell
Ok, just to provide the complete picture. The wrong ARCHFLAGS were due to an evil override in the Rakefile itself. This has now been fixed and I'll be publishing a new release soon.
Add a comment
Comments are now closed for this issue.


WHY WOULD I JOIN???
Are you a market stall owner? A female doctor? An advisor? A mechanic? Or part of a female social or sporting group and wondered where you can advertise? Look no further Fembuiz is here, here you can advertise within a target audience along with many other female and female oriented businesses. To start creating your business profile first you need to select what period of time you would like to be listed on the database for, this can be renewed later if you change your mind. We have two options, 6 months or 12 months, with the 12 months option at $99 including GST, (that’s just $8.25 per month) here there are no options to pay extra to be bumped to the top of the list, we like to keep it fair. All accounts are the same profile design and self managed, so you can come back at any time and make changes to your contact details, photo gallery, business categories, social media links or to your URL media library. We want you to be able gain more customers, so let’s get started …
| Level | Price | |
|---|---|---|
| Six Month Membership | $55.00 now. Membership expires after 6 Months. | |
| Twelve Month Membership | $99.00 now. Membership expires after 12 Months. | |
| Charity/Not For Profit | Free |


{% extends "myroot/layout_auth.html" %} {% load static %} {% block extra_styles_head %} {% endblock %} {% block content %}
Welcome to Django's create user form tutorial, you can test to submit any user information and see how the form respond.
How this user creation form was built? Learn more ».
Have an account? Log in


Home
About
Contact
Sign Up
Log In
Meet the team
Katrina Finney -
Web UI Developer
Luis Schekerka -
Web UI Developer
Suffyan Tariq -
Web React Developer
Oladimeji Anthony Ojo -
Web React Developer
John Mulongo -
Web React Developer
Ty Lippe -
Backend Developer and Project Lead


Vocalize
Home
Log In
Register
Contact
Singing Basics
Sound References
Welcome to Vocalise
The digital vocal coach you use anywhere at any time
User Login
Registration
Michelle Osborne
<EMAIL_ADDRESS>QUICK WARM UP


--- layout: page title: About header-img: "img/about-bg.png" ---
Cat Glenn teaches elementary school computers, an unexpected career following her completion of a Bachelor's degree in History completed in May 2016. Computer science has grown from a lucky career find into a passion that she is thrilled to pursue through the Flatiron School's Fullstack Web Development program!


Lasso mode
Simple Lasso mode based on the C-like mode. Depends on XML, JavaScript, CSS, HTMLMixed, and C-like modes.
MIME types defined: application/x-httpd-lasso
(HTML with Lasso code), text/x-lasso
(plain, non-wrapped Lasso code).
Simple Lasso mode based on the C-like mode. Depends on XML, JavaScript, CSS, HTMLMixed, and C-like modes.
MIME types defined: application/x-httpd-lasso
(HTML with Lasso code), text/x-lasso
(plain, non-wrapped Lasso code).


Registration
First Name:
Last Name:
Residential Address:
Contact Number:
Email address:
Example<EMAIL_ADDRESS>Adhar Number:
Example: xxxx-xxxx-xxxx-xxxx
Gender:
Male
Female
Country:
--Please Select--
India
United States
Canada
United Kingdom
Others
I hereby accept the terms and conditions for using this site
Register
Already regsitered?


--- layout: post title: Oriflame Tender Care Vanilla Review tags: - Oriflame status: publish type: post published: true meta: _edit_last: '2' _aioseop_keywords: Oriflame Tender Care Vanilla Review, Oriflame Tender Care _aioseop_title: Oriflame Tender Care Vanilla Review _yoast_wpseo_linkdex: '0' _thumbnail_id: '5309' _yoast_wpseo_focuskw: '' _yoast_wpseo_title: '' _yoast_wpseo_metadesc: '' _yoast_wpseo_metakeywords: '' _yoast_wpseo_meta-robots-noindex: '0' _yoast_wpseo_meta-robots-nofollow: '0' _yoast_wpseo_meta-robots-adv: none _yoast_wpseo_sitemap-include: ! '-' _yoast_wpseo_sitemap-prio: ! '-' _yoast_wpseo_canonical: '' _yoast_wpseo_redirect: '' ---
Winter is all about warmth coziness, comfortable blankets and my mug of tea. I am not much of a coffee person, It has to be all about tea for me. Winter also brings to my mind vanilla fragrance, so Oriflame Tender Care Vanilla has to be the perfect companion at this time of the year for me. But this one is a Limited Edition from Oriflame...
About: All of the benefits of legendary Tender Care, with a delicious vanilla fragrance. A softening and protecting formula for lips, face, cuticles or any area that is dry and rough.
Price: Rs. 199 for 15 ml.
Loved the quotation on the inner side of carton...
Tender care protecting balm is a cult favorite from Oriflame and probably the best selling product across countries. I had picked up the Limited edition chocolate variant and was quite pleased with it, so I decided to give this one a try too
It smells wax and slight hint of vanilla, which is neither irritating, nor very pleasant. It similar to its other variants reviewed here.
Of all 3 variants the chocolate one is my favorite and Oriflame should give it a thought to make it a permanent collection.
I am sure you have also tried the Oriflame Tender care balm.. Did you like it ?


Emotional intelligence is the awareness of one's emotions and the emotions of others. When practising emotional intelligence, we can separate ourselves from our current emotional stream and recognise how our emotions are affecting or can affect our thoughts and behaviours. We are in turn, able to maintain a healthy relationship with our emotional responses and navigate life away from destructive impulses and habits. Emotional intelligence also covers the understanding of others through non-verbal cues and in a broader sense, the ability to be empathetic.
IQ differs from EQ as it is the quantifiable measurement of ones ability to think logically, analytically and methodically. EQ is not measurable in this sense and is based on ones own lived emotions and how we navigate said emotions.
Emotional intelligence is important because when are aware of our emotions and our emotional responses, we are better equipped in dealing with the chaos and uncertainty that we face within our lives.


Salmon Cookies Branches
Our products can be found around our branches all over the world here is our branches and hours open in each branch:
- Seattle: 6AM Till 8PM
- Tokyo: 6AM Till 8PM
- Dubai: 6AM Till 8PM
- Paris: 6AM Till 8PM
- Lima: 6AM Till 8PM
Some of our best products that you can find while visiting our shops:
-
chinook Fish:
chinook is one of our high requested fish it is a very cool looking fish
-
Salmon Fish:
Who dosent like salmon fish it is the best
-
Colored Fish:
It is always targeted by Kids they love colorful stuff
-
Fish Cutter:
It good for moms to bake some cookies to their kids rather than seening the cookies in there old fashion way CIRCLE make them like fish
-
Frosted-cookies:
If your mom doesnt want to make cookies we got you covered we have the tastiest cookies in the planet
-
Fish Shirt:
Talking about high quality shirt this one of our top merchandise all the customers love it
-
Family Product:
Our Products are for every member of family
Sales Sheet:
In case you are curious about our sales we will provide you a table of our sales in all of our branches Click HERE


The day started out just like any other sunday, me waking up to an empty house . I was a little 'hungover' from the previous night of drinking like a maniac. As I started to get ready to shower, I remember that a friend had given me two little pink pills looking similar to Oxyconton pills but these had a little 'alpha' sign on them.
Not wanting to be caught with 'crazy pills' I hid them away so as no one searching through my pants for money, would find them. Althought no one was around, paranoia never really leaves you once you've been on a heavy coke binge. Being bored after the shower I decided to down the pills. So cranking the Basement Jaxx up to the max on my little stereo I danced around the room in a ballet manner as I gulped the little pieces of candy down with a tall glass of ice cold water. The onset was not quick, maybe thirty minutes or so, but it kicked in and made me feel this warm rush at first which lasted about a minute.  I plopped down, looked at my ceiling which was now darkened slightly (I later found I had knocked a light over on the way to my bed) and felt really drowsy.  This was a nice plan until he passed out cold due to beer intoxication.
Needless to say I fell asleep about one and a half hours after consumption of the little tricks. A lot of my friends get a big bang outa these 'Z-Bars' and I dont mean to discourage anyone but these things suck! Vicodin will always be my champion.
++++++++++++EXPERIENCE 2+++++++++++++
!!!2 WEEKS AFTER THE FIRST !!!
Thinking maybe I did something wrong in the consumption department of Alprazolam, I decided to insufflate half a crushed 0.5mg pill. So it was like snorting 0.25 mg of Xanex powder.
Well here's how it went. Another stressful day at work dealing with junkie bastards haggling me to show them all of our items. I take a bathroom break to get away from all the madness and recover the little Alprazolam pill my friend M gave to me the previous night. I placed the little orange/pink pill on the bathroom sink and proceeded to crush it using my lighter as a pestle to mash the little bugger into submission I had my special razor blade and snorting bill, used in previous acts of insufflation, handy and cut myself out 2 lines from half the pill mash. I placed the rest of the crushed residue in a homemade envelope, proceeded to snort down the two lines with no resistance from mucous or any other obstruction in my otherwise clean nose.
2 SECONDS AFTER INSUFFLATION I BLACKED OUT AND LANDED ON THE TOILET SEAT IN(thank satan)SITTING POSITION. I WAS BLACKED OUT FOR ABOUT 2 REAL TIME MINUTES. When I came to, I felt really drowsy , I could barley move and took some time to get myself straight. I gathered my thoughts and drunkenly opened the door, clocked out and went home 'sick.' Upon arrival , I was met with warm pizza. I ate 2 slices and went to bed.
I AM NEVER DOING THIS BULLSHIT DRUG AGAIN!!!! But that is my opinion and will stay so. I do not want to cause anyone to NOT use this substance. But foe me personally it didn't tickle my fancy. Have fun and be safe. NO DRINKING AND DRIVING!
Experience Reports are the writings and opinions of the individual authors who submit them.
Some of the activities described are dangerous and/or illegal and none are recommended by Erowid.


Getting Over It Custom Maps
A place where you can find and play custom maps for getting over it!
Modpack
Download
Mapping
Server
Mapping
Tutorial
Submit a
Map
Filter By
Creator
Map Length


NLS Books
Announcements Generator
{1} {m}
by {m}
DB
Copyright
This is a new recording of: DB#
Read by:
BLANK was unavailable to continue reading of this series.
This book contains BLANK pages.
Approximate reading time: ____ hours, ____ minutes.
This book contains markers allowing direct access to the CONTENTS_PARTS_and_ETC.
This book contains markers allowing direct access to: at level 1 the CONTENTS_PARTS_and_ETC and at level 2 the SECTIONS_CHAPTERS_and_ETC.
This book contains markers allowing direct access to: at level 1 the CONTENTS_PARTS_and_ETC; at level 2 the SECTIONS_CHAPTERS_and_ETC; and at level 3 the SUBSECTIONS_EXERCISES_and_ETC.
This book contains markers allowing direct access to: at level 1 the CONTENTS_PARTS_and_ETC; at level 2 the SECTIONS_CHAPTERS_and_ETC; at level 3 the SUBSECTIONS_EXERCISES_and_ETC; and at level 4 the SUBSECTIONS_EXERCISES_and_ETC.
{1} Library of Congress Annotation: {m}
From The Book Jacket:
About The Author:
Other Books By:
{8} Reader's Note: {7}
{1} End of:
by {m} (SPELL)
Read by:
in the studios of the American Printing House for the Blind, Louisville, Kentucky, for the Library of Congress, _________, .
Published by: BLANK
Further reproduction or distribution in other than a specialized format is prohibited. If you found this book to be defective, please contact your cooperating network library.
{m}
by
DB
Approximate reading time: [00] hours, [00] minutes.
End of:
by {m} (SPELL)
Further reproduction or distribution in other than a specialized format is prohibited. If you found this book to be defective, please contact your cooperation network library.


Memory management bugs, in particular incorrect uses of free, are notoriously hard to debug because the symptoms of the problem show up in a place far disconnected from where the bug actually occurred. For instance, an incorrect free can lead to corruption of a completely unrelated object allocated later.
Debugging allocators such as Dmalloc, and tools such as Valgrind and Purify provide some help, by detecting when freed objects are accessed (Valgrind, Purify) or modified (Dmalloc). However, these tools cause large slowdowns, making them unsuitable for anything but debugging, and they still only report problems after the fact (at the bad access) rather than at the bad free itself.
HeapSafe is the part of Ivy that directly checks that a program uses free safely, with time and space overheads low enough (normally below 30% for single-threaded code) that it can be used all the time. Furthermore, when HeapSafe does detect an invalid free, it can simply leak the object (and log the problem), preventing the program from failing.
HeapSafe has two significant limitations. First, it is not fully sound (i.e., it can miss or misreport bad frees), mostly because of limitations of C itself, such as the lack of array bounds checks (see Safety in HeapSafe). Finally, HeapSafe does not detect memory leaks, as it only checks the soundness of existing frees. Unlike the earlier, standalone, release of HeapSafe, the version of HeapSafe integrated with Ivy does support multi-threaded code (though with higher runtime overheads).
Applying HeapSafe to a program generally requires limited source code changes, both to use HeapSafe's extended memory management API (see Deallocation Safety), and to help the runtime library track pointers to heap objects (see Tracking Pointers). The modified source code can still be compiled and run without HeapSafe (the HeapSafe header file defines HeapSafe's operations in terms of the standard C library when HeapSafe isn't used).
Our experience is that applying HeapSafe to existing medium-size programs is generally easy. Applying HeapSafe to larger programs like Perl or the Linux kernel is more complex, but still quite tractable (a few man-weeks of effort). HeapSafe includes a special debugging mode which simplifies porting programs by tracking the source of all pointers to objects (and where they were last written), at the cost of a substantial slowdown (up to 4x slower).
HeapSafe is implemented as a C-to-C compiler using gcc as its backend. The currently supported platforms are Linux and Mac OS X.
HeapSafe maintains a reference count for each object, i.e., a count of the number of pointers to each object. A deallocation of an object O is safe if O's reference count is zero[#]_.
| [1] | Reference counts due to internal references within O are removed prior to this check. |
The HeapSafe compiler transforms C programs to update reference counts on every pointer write. The HeapSafe runtime library includes:
- Replacements for C's memory management functions (malloc, calloc, realloc and free). These replacements:
- clear memory when it is allocated (i.e., malloc behaves like calloc), to avoid corrupting reference counts on the first write of a pointer
- check deallocation safety in free and realloc
- Support for delayed free scopes, which delay deallocation and its associated reference count check. These scopes are key to making HeapSafe's checks practical (see Deallocation Safety).
- Replacements for C's memcpy, memmove and memset functions that update reference counts correctly when copying pointers.
Using HeapSafe and its runtime library instead of gcc is as simple as replacing uses of gcc by ivycc --heapsafe, and #including the heapsafe.h header file which declares HeapSafe's runtime library. HeapSafe's symbols start with hs_, HS_ or RC_ to avoid name conflicts (e.g., HeapSafe's malloc replacement is hs_malloc).
HeapSafe also includes a header file, hslib.h, which redefines a few standard C library functions (in particular, the malloc, calloc, realloc and free memory management functions) in terms of HeapSafe functions to simplify porting.
At startup, programs compiled with HeapSafe check the HEAPSAFE environment variable to set various options (see HEAPSAFE Environment Variable for full details). In particular:
- If HEAPSAFE=log, then HeapSafe will print the number of bad frees (along with a few other statistics) when the program exits.
- If HEAPSAFE=forcefree, then HeapSafe will free objects that fail their deallocation check rather than silently leaking them. This may be a better option early in the conversion process to HeapSafe when many deallocations fail.
Use HEAPSAFE="forcefree log" if you want both behaviours.
With hslib.h included and HEAPSAFE=forcefree, most C programs can immediately be run with HeapSafe. They will however most likely report a number of bad frees, which you will need to address... See A Typical Conversion to HeapSafe for more details.
A final note: HeapSafe's reference counts are stored in a 512MB array that is declared by the runtime library. Because of Linux's lazy page allocation strategy, the system only allocates as pages for those reference count entries that are actually used - this leads to a 12.5% memory overhead for reference counting (see Implementation Overview). However, if your machine does not have 512MB of virtual memory (e.g., you have little RAM and no swap space configured), Linux will just kill your program on startup (and print Killed). This can be fixed by setting /proc/sys/vm/overcommit_memory to 1:
# do this as root echo 1 > /proc/sys/vm/overcommit_memory
Checking that an object's reference count is zero at deallocation time ensures that no pointers remain to the object, hence no subsequent access can corrupt the deallocated memory. In many cases, the pointer passed to free is already the only remaining pointer to the object, so as long as that pointer is zeroed-out, the deallocation is safe. HeapSafe provides a macro, HS_ZFREE, which frees an object and zeroes-out its argument, directly supporting this common case. For instance, the following program will run without HeapSafe reporting any problems:
#include <heapsafe.h> int *mem; int main() { mem = hs_malloc(100 * sizeof(int)); ... HS_ZFREE(mem); }
If free was used instead of HS_ZFREE, HeapSafe would report that the deallocation was bad, as the global variable mem would still point to the object.
Note that objects stored in local variables do not need to be zeroed-out as long as the local variable is dead (not subsequently used without being reassigned) after the free. If mem becomes a local variable, the example above can be written as:
#include <heapsafe.h> int main() { int *mem = hs_malloc(100 * sizeof(int)); ... HS_FREE(mem); }
The HS_FREE macro does not zero-out its argument; it is the most direct replacement for the standard free function when using HeapSafe.
When several pointers point to the object being freed, HS_ZFREE is not sufficient. One solution is to zero-out all the other pointers to the object to be deallocated:
#include <heapsafe.h> int *mem, *scan; int main() { mem = hs_malloc(100 * sizeof(int)); for(scan = mem; scan < mem + 100; scan++) *scan = 42; scan = NULL; /* Without this, the free will fail */ HS_ZFREE(mem); }
Zeroing-out scan is necessary as it still points to the end of the object in mem.
In some cases, zeroing-out pointers is not very practical. Consider for instance deallocating a circular linked-list (where the last element points to the first):
void free_loop(struct loop *start) { struct loop *next, *cur = start; do { next = cur->next; free(cur); cur = next; } while (cur != start); }
When the first element is freed, there remains a pointer from the last element (which will not be deallocated until the end of the list is reached). While it would be possible to modify the code to make the list non-circular, this would complicate the code (possibly introducing bugs). And for more complex data structures, the code to zero-out internal data structure pointers could become quite complicated, especially as it must still be possible to free the whole data structure afterwards.
To get around this problem, HeapSafe introduces a small extension to the memory management API, delayed free scopes. Delayed free scopes are based on the observation that while pointers often remain to deallocated objects, these pointers are generally soon overwritten or are themselves found in objects that are soon deallocated (e.g., because they are part of the same data structure, as in the circular list example). With delayed free scopes, frees requested within the scope are only performed and checked when the scope ends. For instance, the circular list example above becomes:
void free_loop(struct loop *start) { struct loop *next, *cur = start; hs_delayed_free_start(); /* Delay frees until the end of the function */ do { next = cur->next; HS_FREE(cur); cur = next; } while (cur != start); hs_delayed_free_end(); /* Perform delayed frees */ }
If delayed free scopes are nested, deallocations are delayed until the outermost scope ends.
HeapSafe depends on accurate reference counts. Maintaining these requires
- tracking all pointer writes (including, e.g., those done via structure copies or memcpy)
- knowing the types of deallocated objects (to update the reference counts of objects referenced from the now-dead object)
- noticing when a program changes how it uses unions containing pointers (e.g., switches from using an int field in a union to a void *)
To assist in tracking pointers, HeapSafe introduces adjust functions, a form of run-time type information. An adjust function for a type T is a function that will adjust the reference count for all objects referenced by an array of objects of type T. For instance, for the type:
struct doubly_linked_list { int value; struct doubly_linked_list *prev, *next; };
the adjust function adjusts the reference counts of objects referenced by the next and prev fields.
An adjust function has type hs_type_t, defined as:
typedef void (*hs_type_t)(void *x, int by, size_t s);
The function takes a pointer to the array of objects of type T (x), an amount by which to adjust the reference counts (by, must be +1 or -1) and the size (in bytes) of the array of objects (s).
The adjust function for type T is obtained using the hs_typeof( T ) construction. Normally, HeapSafe automatically generates the code for an adjust function, however if type T is (or contains) an union containing pointers, then you have to write an adjust function by hand [1], as HeapSafe has no way of knowing which field of the union is currently in use. For details on writing adjust functions by hand, see Writing Adjust Functions.
| [2] | If a union contains only pointer fields, then HeapSafe can still generate the adjust function. |
Adjust functions are used by HeapSafe's (de)allocation API (hs_typed_realloc, hs_typed_free) and to help HeapSafe track pointer writes.
Pointer writes and copies of structures containing pointers are automatically handled by HeapSafe. To copy a structure of type T, HeapSafe uses T's adjust function, so HeapSafe will ask for a hand-written adjust function when it cannot generate one automatically. For instance, in the following code the programmer must write an adjust function for struct strange:
struct strange { enum { k_integer, k_pointer } key; union { int integer; void *pointer; } values; } a, b; void f(void) { /* This copy requires a hand-written adjust function for strange */ a = b; }
Calling memcpy, memmove and memset (and other similar functions) to copy objects containing pointers will cause HeapSafe's reference counts to go wrong. This can lead to both over-reporting of bad frees (HeapSafe thinks an object is accessible when it isn't) and under-reporting (HeapSafe doesn't realise an object is accessible). To make converting programs for use with HeapSafe simple
HeapSafe reports when it detects a problematical use of memcpy and friends. HeapSafe reports when the type of actual arguments to a particular call to memcpy contains pointers, e.g.:
int **buf1, **buf2; memcpy(buf2, buf1, 10 * sizeof(int *));will report a problem as the type of both buf1 and buf2 (int **) contains pointers. Conversely:
int *buf3, *buf4; memcpy(buf3, buf4, 10 * sizeof(int));will not report any warning as buf3 and buf4 (pointers to integers) do not contain pointers. Note also that these warnings are based on the actual types at the call site, so can be easily fooled. For instance neither of these two uses of memcpy will report warnings:
int **buf1, **buf2; void *x = buf1, *y = buf2; memcpy(y, x, 10 * sizeof(int *)); memcpy((void *)buf2, (void *)buf1, 20 * sizeof(int *));In both cases, the type of the arguments to memcpy is void * which is not known to contain pointers.
HeapSafe's library contains type-aware replacements for memcpy, memmove and memset which make code conversion simple. For instance:
int **buf1, **buf2; hs_memcpy(buf2, buf1, 10 * sizeof(int *), hs_typeof(int *));These functions are identical to the regular C functions except that their name starts with hs_ and they take an adjust function for the type of object being copied as their last argument.
To further simplify code, HeapSafe defines macros which automatically apply hs_typeof to the first argument:
int **buf1, **buf2; HS_MEMCPY(buf2, buf1, 10 * sizeof(int *));These macros work as long as the type of the first argument accurately represents the type being copied. If it doesn't, they shouldn't be used. For instance, the following code is bad:
int **buf1, **buf2; /* This will copy buf1 to buf2 as if there were no pointers. Oops. */ HS_MEMCPY((char *)buf2, (char *)buf1, 10 * sizeof(int *));
If your program contains your own generic functions like memcpy (or built on top of memcpy and friends), and these are applied to types containing pointers, you will need to extend them to take type information like hs_memcpy.
Finally note that there are sometimes generic functions that copy pointers but do not cause reference counts to go wrong even without type information. For instance, qsort can safely sort an array of pointers to objects: its writes only end up permuting the pointers, so do not change the value of any reference counts.
When an object is deallocated, HeapSafe uses its adjust function to update the counts of all referenced objects. Thus the functions that cause deallocation (hs_typed_free and hs_typed_realloc) take an adjust function as their last argument:
#include <heapsafe.h> int main() { int *mem = hs_malloc(100 * sizeof(int)); ... hs_typed_free(mem, hs_typeof(int)); }
As with HS_MEMCPY, the HS_FREE and HS_REALLOC macros simply automate the use of hs_typeof under the assumption that the type of its argument accurately reflects the type of the object being freed, as in the example we saw earlier:
#include <heapsafe.h> int main() { int *mem = hs_malloc(100 * sizeof(int)); ... HS_FREE(mem); }
Like HS_FREE, HS_ZFREE assumes that the type of its argument is correct.
The following code fragment uses a union first to store an integer, then to store a pointer:
struct strange { enum { k_integer, k_pointer } key; union { int integer; void *pointer; } values; } a; int g; void havefun(void) { /* Use a to store an integer */ a.key = k_integer; a.values.integer = 33; ... /* Use a to store a pointer */ a.key = k_pointer; a.values.pointer = &g; }
This kind of code (where a union is switched between different purposes) can cause problems for HeapSafe's reference counts: the write to a.values.pointer assumes it is overwriting a pointer, so will read a.values.pointer's old value to reduce its reference count by one (as it is no longer going to be referenced from there). However, in this case a.values.pointer simply holds a bit pattern corresponding to the integer 33 written earlier. This bit pattern may or may not "point" to some valid object. This can cause reference counts to go wrong.
To avoid these problems, you should either:
- not switch a union between different purposes
- zero-out (set to all 0 bytes) the union before repurposing it - this works because all 0 bytes correspond to NULL pointers[#]_
| [3] | While this is not guaranteed by the C standard, it is true of all common modern architectures. |
To simplify zeroing-out the union part of a larger structure, HeapSafe provides an HS_MUTATE macro which safely zeroes out a union within a structure. Using HS_MUTATE, the havefun function is written:
void havefun(void) { /* Use a to store an integer */ HS_MUTATE(a, values); a.key = k_integer; a.values.integer = 33; ... /* Use a to store a pointer */ HS_MUTATE(a, values); a.key = k_pointer; a.values.pointer = &g; }
Bad frees have two main causes in HeapSafe:
- some pointers to the freed object remain
- the reference count to the object went wrong (e.g., because memcpy was used)
It can be quite tricky to figure out where pointers remain, or where reference counts went wrong. To assist in this process, HeapSafe provides a debugging mode which tracks the origin of all pointers to a particular object. When running a program compiled with the debugging mode, you can call the hsinfo function with any pointer as argument. This call will report:
- where (file, line) the object (if any) referenced by the pointer was allocated
- the source of all pointers to the object and where (file, line) those pointers were written
This information is usually very helpful in adding code to zero-out pointers or figuring out where to place delayed free scopes.
If reference counts have gone wrong, hsinfo will report that its source pointer information is inconsistent with the current memory contents. The object containing the inconsistency is the object that has been overwritten behind HeapSafe's back.
A typical way to use hsinfo is to set a breakpoint in gdb in the forcefree function (part of HeapSafe's runtime library). This function is called on all bad frees, with the object that was not deallocatable as argument. For instance, if you compile the test/simple/fail1 application with HeapSafe's debug mode and run it under gdb, you might get (comments with ***):
.../heapsafe-1.0/test/simple$ ivycc --heapsafe --hs-debug -g fail1.c -o fail1 .../heapsafe-1.0/test/simple$ gdb fail1 *** Stop in forcefree to detect bad frees (gdb) b forcefree Breakpoint 1 at 0x80490c0: file heapsafe_libc_debug.c, line 5653. (gdb) r Starting program: /tmp/heapsafe-1.0/test/simple/fail1 Breakpoint 1, forcefree (h=0x28810040) at heapsafe_libc_debug.c:5653 5653 { *** We got a bad free, find out what it was (gdb) p hsinfo(h) [0x28810040 in O:0x28810050/44 (A:fail1.c:8)] #R:[0x880f624 global] to 0x28810050, W:fail1.c:8 *** There's a reference from the global at address 0x880f624, which was *** written at fail1.c:8. Ask gdb what symbol that is: (gdb) info sym 0x880f624 gx in section .bss *** It's gx. Let's look at out stack trace. (gdb) bt #0 forcefree (h=0x28810040) at heapsafe_libc_debug.c:5653 #1 0x0804ba17 in rcfree (hdr=0x28810040) at heapsafe_libc_debug.c:4328 #2 0x08048b10 in main () at fail1.c:9 (gdb) fra 2 #2 0x08048b10 in main () at fail1.c:9 9 HS_FREE(gx); *** Ahha! We're freeing a global, but gx will still point to *** the freed object. One possible fix: use HS_ZFREE instead.
When using a debugger, it can be useful to compile with the --saveadjust=somedir option, to make the source code for adjust functions available to the debugger. Within gdb, you should then also execute dir somedir to add somedir to your source code search path.
Note that the debugging mode currently does not support multi-threaded code.
The hslib.h header file simplifies initial conversion of program's to use HeapSafe by defining a few C functions (malloc, free, calloc, realloc, memcpy, memmove, memset) in terms of HeapSafe functions and macros. Using hslib.h, the typical steps for converting a program for HeapSafe are:
Modify the Makefile so that it calls HeapSafe rather than the standard C compiler. Furthermore, invoke HeapSafe in debugging mode and force inclusion of hslib.h. This can typically be done by adding:
CC = ivycc --heapsafe --hs-debug --warn-typeof-char -include hslib.hto the Makefile (and removing any previous CC = ... line).
The --warn-typeof-char option instructs HeapSafe to warn when hs_typeof is applied to the char type. This helps detects a few common problems during conversion to HeapSafe:
Casts to char * in arguments to free, memcpy, etc, e.g.
struct T *some_pointer; free((char *)some_pointer);These casts are common in old (pre-ANSI) code, which was written when C did not have a void * type. These casts cause HeapSafe to assume the incorrect type for freed objects (i.e., in this case that we're freeing a char or char array rather than a struct T).
The fix to code like this is normally simple: remove the cast.
Calls to memcpy and friends with char * arguments. These calls may be benign (e.g., copying parts of strings), but may also be related to copying parts of structures containing pointers (via some earlier casts).
Build the project, and note and fix warnings and errors reported by the HeapSafe compiler. These typically include:
- writing adjust functions for types containing unions
- removing casts to void * and char * in deallocation, memcpy, etc functions
You may want to use the --fakeadjust=somedir option to automatically generate an incorrect version of adjust functions for types containing unions . This incorrect adjust function is often a useful starting point for a correct adjust function (in particular, all the parts that do not refer to the union should be fine).
Run the project on test inputs, and search for the causes of the bad frees using HeapSafe's debug facilities (see above).
Fix these bad frees by adding scopes, HS_ZFREE calls, type safety fixes and additional zeroing code.
In some programs it is sufficient to replace all uses of free and realloc by HS_ZFREE and HS_ZREALLOC (this can in fact be a good first step).
Fix any memory management bugs you discover in the process ;-)
Improve performance by
- removing the --debuglib compilation flag
- ensuring that delayed free scopes are not too large
- adding hs_nofree annotations (see Improving performance)
- removing unnecessary memset calls (because HeapSafe's hs_malloc zeroes memory) or using HeapSafe's typed HS_ALLOC and HS_ARRAYALLOC allocation macros (see Allocation and Deallocation)
Optionally, stop using hslib.h by
- ensuring heapsafe.h is included in all your C files
- replacing the functions defined by hslib.h by their HeapSafe equivalent
In this section, we walk through the conversion of the cfrac program to use HeapSafe. HeapSafe's distribution includes two copies of this program: original-cfrac is the original C code, and cfrac is the version modified to use HeapSafe. These programs can be found:
- in the test directory in HeapSafe's source tarball
- at http://memory.intel-research.net/files/examples.tar.gz
cfrac is a program for factoring arbitrary size integers, e.g.,
.../test/original-cfrac$ ./cfrac<PHONE_NUMBER>40421458831903<PHONE_NUMBER>40421458831903 =<PHONE_NUMBER>99 *<PHONE_NUMBER>97
Starting from original-cfrac, we modify the CC= line in the Makefile to read:
CC = ivycc --heapsafe -include hslib.h --hs-debug --warn-typeof-char
Because we will be debugging the code, we specify --hsdebug (and also remove the -O3 option from the CFLAGS= line, to make debugging more convenient). Remember that the -warn-typeof-char option helps detect problems with arguments to memcpy and free.
Compiling the modified project gives the following warnings, which we'll investigate later:
pio.c:44: Warning: type of 'char' requested pio.c:60: Warning: type of 'char' requested pio.c:93: Warning: type of 'char' requested ptoa.c:62: Warning: type of 'char' requested pcfrac.c:432: Warning: type of 'char' requested
No errors are reported and no adjust functions need to be written by hand, so we can just run the resulting program:
.../heapsafe/test/original-cfrac$ ./cfrac 23551 23551 = 11 * 2141
but if we set the HEAPSAFE environment variable to log, we see there are some bad frees:
.../heapsafe/test/original-cfrac$ export HEAPSAFE=log *** use 'setenv HEAPSAFE log' if using tcsh *** all subsequent examples assume HEAPSAFE=log .../heapsafe/test/original-cfrac$ ./cfrac 23551 23551 = 11 * 2141 Log for ./cfrac 23551 ------------------------------------------------------------------ ... 531 bad frees
We didn't set the forcefree option as the memory leaks due to the bad frees do not prevent the program from running. In general, specifying forcefree leads to more innacurate bad free reports, as the pointer(s) that prevented the first free will prevent any subsequent frees that reuse the same memory. During debugging, it's best to only specify forcefree if necessary.
The five warnings reported by HeapSafe are all benign:
The first three warnings turn out to be deallocations of char arrays in pio.c.
pio.c:44: Warning: type of 'char' requested pio.c:60: Warning: type of 'char' requested pio.c:93: Warning: type of 'char' requestedThe warning in ptoa.c related to copying parts of a string with memmove.
ptoa.c:62: Warning: type of 'char' requestedFinally, the warning in pcfrac.c is for an initialisation of an array of type solnvec, which turns out to be an array of characters.
pcfrac.c:432: Warning: type of 'char' requested
Having investigated all these warnings, we remove the --warn-typeof-char option from the Makefile.
It's now time to look into the bad frees, using gdb:
.../heapsafe/test/original-cfrac$ gdb cfrac (gdb) b forcefree Breakpoint 1 at 0x165c3: file heapsafe_libc_debug.c, line 5654. (gdb) r 23551 Starting program: .../cfrac 23551 Breakpoint 1, forcefree (h=0x21808040) at heapsafe_libc_debug.c:5654 (gdb) bt #0 forcefree (h=0x21808040) at heapsafe_libc_debug.c:5654 #1 0x0001380f in rcfree (hdr=0x21808040) at heapsafe_libc_debug.c:4328 #2 0x00016ab7 in hs_typed_free (pp=0x21808050, t=0) at heapsafe_libc_debug.c:5841 #3 0x000034a7 in pfree (u=0x21808050) at pops.c:144 #4 0x000081a2 in atop (chp=0xbffff955 "") at precision.h:62 #5 0x00002eb2 in main (argc=2, argv=0xbffff870) at cfrac.c:224 (gdb) p hsinfo(h) [0x21808040 in O:0x21808050/12 (A:pops.c:102)] #R:[0xbffff778 in local 0xbffff778/4] to 0x21808050, W:precision.h:72
The first bad free is for object with address 0x21808050 [2]. It's referenced from a 4-byte local at address 0xbffff778, which was last written at precision.h:72 (in an inline function called psetq). Generally, the easiest way to find references from locals is to use gdb's bt full command. Using that, we find that the local variable referencing 0x21808050 is clump, in the atop function.
| [4] | The 0x21808040 value for h passed to forcefree is the address of the object's debug header. |
Walking up the call stack, we see we're at a call to pdestroy(clump) in atop. Further investigation reveals that pdestroy is a function that decrements the reference counts of arbitrary precision integers and deallocates them when the count is zero (note that these are cfrac's reference counts, not HeapSafe's...).
HeapSafe is not allowing the free, because clump still points to the object after the call to pdestroy (clump is a local variable, but it's address was taken so it is considered live until the end of atop). A bit of examination of the code shows that pdestroy is used to get rid of a reference, so it's reasonable to have it zero it out too. So we'll change pdestroy to zero it's argument, somewhat like HS_ZFREE. The old code for pdestroy is
static inline void pdestroy(precision u) { if (u != pUndef && --(*(prefc *) u) == 0) pfree(u); }
which we replace with
#define pdestroy(u) \ do { precision __tmp = (u); u = 0; actual_pdestroy(__tmp); } \ while (0) static inline void actual_pdestroy(precision u) { if (u != pUndef && --(*(prefc *) u) == 0) pfree(u); }
With this change, we have only 8 bad frees left:
.../test/original-cfrac $ ./cfrac 23551 23551 = 11 * 2141 ... 8 bad frees
Returning to gdb
(gdb) r 23551 Starting program: .../cfrac 23551 Breakpoint 1, forcefree (h=0x21808840) at heapsafe_libc_debug.c:5654 (gdb) p hsinfo(h) [0x21808840 in O:0x21808850/12 (A:pcfrac.c:76)] #R:[0x218088e0 in O:0x218088d0/44 (A:pcfrac.c:166)] to 0x21808850, W:pcfrac.c:177
There's a reference to 0x21808850 (allocated at pcfrac.c:76) from heap object 0x218088d0 (allocated at pcfrac.c:166). The reference was written at pcfrac.c:177. Walking up the call stack, we see that we're in function freeSoln in pcfrac.c, and that we're doing:
free(p->e); /* BitVector */ free(p);
p->e is 0x21808850 and p is (unsurprisingly) the 0x218088d0 object with the remaining reference to p->e.
There are two obvious ways to change this code for HeapSafe: use HS_ZFREE(p->e), or wrap the two frees in a delayed free scope. Let's do the latter:
hs_delayed_free_start(); free(p->e); /* BitVector */ free(p); hs_delayed_free_end();
Before recompiling, let's check the next bad free:
(gdb) c Continuing Breakpoint 1, forcefree (h=0x218088c0) at heapsafe_libc_debug.c:5654 (gdb) p hsinfo(h) [0x218088c0 in O:0x218088d0/44 (A:pcfrac.c:166)] #R:[0x21808058 in O:0x21808050/44 (A:pcfrac.c:513)] to 0x218088d0, W:pcfrac.c:627
The free of p failed too, due to a reference from 0x21808050 allocated at pcfrac.c:513, which is
b = (SolnPtr *) malloc(bsize);
Walking up the call chain, we're currently in pcfrac.c at:
if (b != (SolnPtr *) 0) for (j = 0; j <= m; j++) freeSoln(b[j]);
So we're freeing a bunch of solutions in array b. We could simply zero-out the elements of array b before calling freeSoln:
if (b != (SolnPtr *) 0) for (j = 0; j <= m; j++) { SolnPtr p = b[j]; b[j] = NULL; freeSoln(p); }
but this is not so nice. Presumably b is going to be freed or reused sometime soon, as it contains all these pointers to deallocated memory. But after investigation, we see there's no free of b (a local variable), which means cfrac has a minor leak. Let's fix the leak:
if (b != (SolnPtr *) 0) { for (j = 0; j <= m; j++) freeSoln(b[j]); free(b); }
Now we can simply wrap all this code in a delayed free scope:
if (b != (SolnPtr *) 0) { hs_delayed_free_start(); for (j = 0; j <= m; j++) freeSoln(b[j]); free(b); hs_delayed_free_end(); }
When we recompile and run, we get:
../test/original-cfrac $ ./cfrac 23551 23551 = 11 * 2141 ... 0 bad frees
Yeah!
We might think the first delayed free scope we added is redundant (it's encompassed by the second one), but if we remove it we get 2 bad frees. It turns out freeSoln is also called from freeSolns, so it still needs the delayed free scope.
Checking cfrac with more inputs reveals no more bad frees:
../test/original-cfrac $ ./cfrac<PHONE_NUMBER>930000000057<PHONE_NUMBER>930000000057 =<PHONE_NUMBER>03 *<PHONE_NUMBER>9 ... 0 bad frees ../test/original-cfrac $ ./cfrac<PHONE_NUMBER>40421458831903<PHONE_NUMBER>40421458831903 =<PHONE_NUMBER>99 *<PHONE_NUMBER>97 ... 0 bad frees
It looks like we're done :-)
We may still be concerned by performance. Let's check HeapSafe's impact on cfrac's performance. We remove the --hsdebug and readd the -O3 options in the Makefile. We get (all times are measured on a 2.33GHz Intel(R) Xeon(R) 5140):
../test/original-cfrac $ ./cfrac<PHONE_NUMBER>658048720145358906686592706357<PHONE_NUMBER>658048720145358906686592706357 =<PHONE_NUMBER>5827702811 *<PHONE_NUMBER>7317083887 Log for ./cfrac<PHONE_NUMBER>658048720145358906686592706357 ------------------------------------------------------------------ cputime: 14.40
And on the original code:
$ time ./cfrac<PHONE_NUMBER>658048720145358906686592706357<PHONE_NUMBER>658048720145358906686592706357 =<PHONE_NUMBER>5827702811 *<PHONE_NUMBER>7317083887 real 0m11.450s user 0m11.449s
However, this is not quite comparing like with like, as HeapSafe is built over Doug Lea's malloc implementation (v2.8.3), which is not the same as Linux's default malloc. If we use this malloc with the original code, we get an execution time of 10.7s.
The actual slowdown is noticeable (35%). If we compile with --hslib=stats, to get some memory allocation statistics
55558848 allocations, 55558848 frees (8427 scoped)<PHONE_NUMBER> actual bytes max actual memory use: 547925
we see this program is allocating ~1600MB of data ("actual bytes"). With HeapSafe, all this has to be zeroed first - maybe this isn't necessary?
A bit of investigation reveals that most of cfrac's allocation is for big integers, occurring at the palloc function in pops.c. We can replace
w = (precision) allocate(PrecisionSize + sizeof(digit) * size);
by
w = (precision) HS_ARRAYALLOC(char, PrecisionSize + sizeof(digit) * size);
because the precision type contains no pointers (precision is a type with a variable-sized array at the end, so we have to cheat on the type we pass to HS_ARRAYALLOC). With this change, runtime drops to 13.74s from 14.4s (overhead is now 28%).
Finally, we note that several very-commonly-called functions (palloc, pnew, pparmq, presult) cannot free memory. We add hs_nofree qualifiers to them. We also have to add hs_nofree to errorp which is called by palloc to handle out-of-memory conditions. Execution time drops to 13.18s and overhead is now a reasonable 23%.
This section presents the HeapSafe language extensions and runtime library. It also briefly discusses how to compile a program modified for HeapSafe without HeapSafe, and the HEAPSAFE environment variable which is used to set runtime options for HeapSafe programs. It does not discuss the HeapSafe-specific options to ivycc -- these are covered in the ivycc(1) man page.
One of the goals of HeapSafe is to allow programs written for HeapSafe to be compiled and run with any C compiler. All HeapSafe files must #include <heapsafe.h>. When compiled with a regular C compiler this header file defines HeapSafe's library and language extensions in terms of regular C operations. The only differences between the resulting program and one compiled with HeapSafe are:
HeapSafe detects bad frees.
Delayed frees can hide errors: If a program frees an object within a delayed free scope, and then erroneously accesses the object before the delayed scope has ended then HeapSafe will hide this error. If the program is run without HeapSafe then it is possible that the program will access a newly allocated object.
We may in the future provide an unchecked implementation of delayed free scopes to avoid this issue.
HeapSafe provides a few extra type qualifiers to handle various issues related to reference counting:
hs_norc: This qualifier can be added to any pointer type to disable reference counting, e.g., int *hs_norc x. It can be useful when interacting with code not compiled by HeapSafe (see Interactions with External Code) or in special circumstances where you want to keep dangling pointers to deallocated memory (this is of course unsafe).
hs_untyped: This qualifier can be added to a function declaration to get a warning whenever the function is called with arguments that contain pointers. For instance, the heapsafe.h header file includes:
void *memcpy(void *to, const void *from, size_t s) hs_untyped;to get warnings when memcpy is used to copy pointers. Adding hs_untyped to memcpy-like functions in external libraries can be helpful when converting code to HeapSafe.
hs_nofree: Placing this qualifier on functions that perform no memory deallocation can improve performance. A function qualified with hs_nofree can only call other functions qualified with hs_nofree. See Improving Performance for more details.
The hs_typeof language extension returns the adjust function for a given type, e.g., hs_typeof(int *). It can also be applied to an expression, in which case it returns the adjust function for the type of the expression (note that unlike C's sizeof, parentheses are required around an expression, i.e., hs_typeof x+2 will produce a compile-time error).
The result of hs_typeof has type hs_type_t, defined as:
typedef void (*hs_type_t)(void *x, int by, size_t s) hs_nofree;
If the type contains no pointer, hs_typeof returns ((hs_type_t)0). Applying hs_typeof to an array type returns the same result as applying it to the array's base type (e.g., hs_typeof(struct X []) == hs_typeof(struct X)).
An adjust function for type T takes three arguments:
- x is a pointer to a memory block containing one or more objects of type T
- by must be +1 or -1
- s indirectly specifies the number of objects referenced by x:
- if s == 0, then x refers to a single object
- otherwise, x refers to however many (but at least one) objects of type T fit in s bytes (s need not be the size to an exact number of objects)
The adjust function must adjust the reference counts for the object(s) pointed to by pointers in the objects at x by amount by. For instance, if the adjust function for type:
struct doubly_linked_list { int value; struct doubly_linked_list *prev, *next; };
is called as follows[#]_:
struct doubly_linked_list elems[2]; (hs_typeof(struct doubly_linked_list))(x, +1, 1 + sizeof elems);
then the reference counts of the objects pointed to by elems[0].prev, elems[0].next, elems[1].prev, elems[1].next will be increased by one. Note that the 1 + applied to sizeof elems had no effect as a struct doubly_linked_list is bigger than one byte.
| [5] | Adjust functions calls are normally only made in the HeapSafe library and in the code generated by the HeapSafe compiler. |
HeapSafe will automatically generate adjust functions for:
- all pointer types
- struct types, as long as for all unions contained (i.e., directly embedded, not accessed via a pointer) in the struct:
- the union does not contain any pointers,
- or, all the pointers in the union have the hs_norc qualifier
- or, all the fields in the union are pointers
For structures that end in open arrays, i.e., structures like:
struct open_array { int length; void *pointers[]; };
HeapSafe assumes that the memory block passed to the adjust function refers to a single object, i.e., that the open array extends to the end of the memory block (whose size is specified by the adjust function's s argument). If this is not true, you will have to write your own adjust function.
When HeapSafe cannot generate an adjust function, you have to write your own - this can only occur for structures or unions. Furthermore, if you wish, you can always write adjust functions by hand, e.g., if the automatically generated one is not appropriate.
If the type needing an adjust function is struct T or union T, the adjust function must be called rc_adjust_T. It must be declared prior to where the adjust function is first needed. So for instance:
struct strange { enum { k_integer, k_pointer } key; union { int integer; void *pointer; } values; } *a; void f(void) { hs_typed_free(a, hs_typeof(struct strange)); } void rc_adjust_strange(void *x, int by, size_t s) { ... }
will report an error as rc_adjust_strange is not declared when hs_typeof is used. Adding a declaration for:
void rc_adjust_strange(void *x, int by, size_t s);
at the start of the file fixes the problem.
The typical adjust function for type T has the following format:
#ifdef __HEAPSAFE__ void rc_adjust_T(void *x, int by, size_t s) { struct T *p = x; /* or, in unusual cases, union T *p */ RC_ADJUST_START(p, s); ... call RC_ADJUST(p->f, by) on all pointer fields f of T ... RC_ADJUST_END(p, sizeof *p); } #endif
The #ifdef __HEAPSAFE__ ensures the adjust function is only compiled if HeapSafe is used. The RC_ADJUST_START and RC_ADJUST_END take care of the looping over the one or more objects of type T. The adjust function for struct strange is:
#ifdef __HEAPSAFE__ void rc_adjust_strange(void *x, int by, size_t s) { struct strange *p = x; RC_ADJUST_START(p, s); if (p->key == k_pointer) RC_ADJUST(p->values.pointer, by); break; RC_ADJUST_END(p, sizeof *p); } #endif
Note that writing adjust functions for unions not embedded in structures may be tricky, as there is no obvious source of information on which field is currently selected. You may need to modify your program a little if it needs adjust functions for unions (e.g., if it's copying union values).
HeapSafe's core allocation and deallocation functions are:
void *hs_malloc(size_t n); void *hs_calloc(size_t n, size_t s); void *hs_typed_realloc(void *p, hs_type_t t, size_t n); void hs_typed_free(const void *p, hs_type_t t);
These functions behave like their standard C counterparts, except that:
- hs_malloc clears the allocated memory
- hs_typed_free and hs_typed_realloc take an adjust function argument that describes the type being de/re-allocated
- deallocation is delayed if it occurs inside a delayed free scope (see below)
HeapSafe defines four macros that simplify using the deallocation functions:
#define HS_REALLOC(p, n) hs_typed_realloc((p), hs_typeof(*(p)), (n)) #define HS_FREE(p) hs_typed_free((p), hs_typeof(*(p))) #define HS_ZFREE(x) ... #define HS_ZREALLOC(x, size) ...
HS_FREE and HS_REALLOC fill in the adjust function based on the static type of the object being deallocated. HS_ZFREE and HS_ZREALLOC do the same, but also zero-out their argument.
The overhead of clearing memory in hs_malloc can be noticeable in programs performing a lot of allocation. Because HeapSafe only depends for correctness on pointers being cleared, performance can sometimes be improved by using HeapSafe's type-sensitive allocation macros:
#define HS_ALLOC(type) ... #define HS_ARRAYALLOC(type, n) ...
HS_ALLOC allocates and returns a pointer to one object of type type, with all pointers zeroed-out. HS_ARRAYALLOC behaves identically, except that it allocates an array of n objects of type type.
The following two functions mark the start and end of delayed free scopes:
void hs_delayed_free_start(void); void hs_delayed_free_end(void);
All deallocations (from calls to hs_typed_free and hs_typed_realloc) that occur within a delayed free scope are delayed until the scope ends. When scopes are nested, deallocations are delayed until the end of the outermost scope.
Checks for bad frees are also delayed until the end of the outermost scope, and pointers between the deallocated objects do not count towards the objects reference counts (i.e., you can deallocate two objects that point to each other within a delayed free scope).
The following three functions replace C's memcpy, memmove and memset functions with versions that understand how to copy pointers:
void *hs_typed_memcpy(void *to, void *from, size_t s, hs_type_t t); void *hs_typed_memmove(void *to, void *from, size_t s, hs_type_t t); void *hs_typed_memset(void *to, int c, size_t s, hs_type_t t);
These functions behave identically to the standard C functions except that they take an adjust function describing the type of the objects being copied/set as their last argument.
In many cases it is possible to use the HS_MEMSET, HS_MEMMOVE and HS_MEMCPY macros that automate the selection of the adjust function based on the static type of the first argument:
#define HS_MEMCPY(to, from, size) \ hs_typed_memcpy((to), (from), (size), hs_typeof(*(to))) #define HS_MEMMOVE(to, from, size) \ hs_typed_memmove((to), (from), (size), hs_typeof(*(to))) #define HS_MEMSET(to, c, size) \ hs_typed_memset((to), (c), (size), hs_typeof(*(to)))
When modifying the selected field of an union containing pointers (see Modifying Unions) it is necessary to zero-out the union to avoid corrupting reference-counts. The following function can be used to simplify this process for unions contained within a larger object:
void hs_typed_mutate(void *obj, void *union_part, hs_type_t obj_t, size_t union_s);
The arguments to hs_typed_mutate are:
* ``obj``: the larger object containing the ``union`` to be zeroed-out * ``union_part``: the ``union`` to be zeroed-out * ``obj_t``: the adjust function for the larger object * ``union_s``: the size in bytes of the ``union``
The HS_MUTATE macro simplifies use of hs_typed_mutate:
#define HS_MUTATE(obj, union_path) \ hs_typed_mutate(&(obj), &(obj).union_path, hs_typeof((obj)), \ sizeof((obj).union_path))
The obj argument is the structure containing the union, and union_path is the access path to reach the union field in obj.
The HS_DESTROY macro simplifies implementing type-specific custom memory allocators in HeapSafe (see Custom Memory Allocators):
#define HS_DESTROY(p) ...
Calling HS_DESTROY(p) zeroes out all pointers in the object pointed to by p, updating reference counts as necessary.
The hslib.h header file simply #includes heapsafe.h and defines the following macros:
#define malloc hs_malloc #define calloc hs_calloc #define realloc HS_REALLOC #define free HS_FREE #define memset HS_MEMSET #define memcpy HS_MEMCPY #define memmove HS_MEMMOVE
These macros redefine the parts of C's standard library that are changed by HeapSafe in terms of HeapSafe's operations, simplifying conversion of programs to HeapSafe.
The HEAPSAFE environment variable controls some aspects of HeapSafe's behaviour (it is read before the program starts, so cannot be modified within the program). This environment variable must contain a series of space-separated options. Supported options are:
log: Print information on bad frees and other statistics.
shortlog: Print the same information as log but in a comma-separated form suitable for pasting into a spreadsheet...
logfile=<path>: Print log information to <path>.
forcefree: Objects should be deallocated even when they have a non-zero reference count. This compromises safety, but avoids bugs causing memory leaks.
slow_realloc: Prevent realloc from reallocating an object in-place, i.e., force it to allocate a new object, copy the data and deallocate the old object.
With this option, realloc behaves "correctly" within a delayed free scope, i.e., the "old" object is only deallocated when the scope ends. However, this can come at a very substantial performance penalty in programs that overuse realloc... Furthermore, having realloc behave correctly does not seem to have any obvious practical advantage.
In this section, we discuss various issues that arise when programming with HeapSafe.
HeapSafe has special handling for local variables:
All pointers in local variables are initialised to NULL (otherwise the first write to the pointer might corrupt some arbitrary reference count depending on the variable's (unitialised) contents).
Local pointer variables (i.e., types like struct X *, but not arrays of pointers, or structures containing pointers) whose address is not taken are handled specially: references from these variables are only included in reference counts at the points P where they are live (i.e., there is a possible read of the variable on some code path starting at P).
For instance, the following code will not report any bad frees:
void f(void) { int *x = hs_malloc(sizeof(int)); *x = 22; HS_FREE(x); if (...) x = hs_malloc(2 * sizeof(int)); else x = NULL; }At the point where x is freed, the local variable x is no longer live as it is reassigned on both branches of the if. If x was a global variable, or if x's address was taken then the call to HS_FREE would report a bad free (HS_ZFREE could be used instead in that case).
References from all other local variables are only removed from reference counts when the function they are declared in exits. So for instance:
void f(void) { int *x[2]; x[0] = hs_malloc(sizeof(int)); x[1] = NULL; ... HS_FREE(x[0]); }will report a bad free.
HeapSafe-compiled programs can be linked with existing binary code. However, two issues may cause problems: sharing objects containing pointers between HeapSafe and non-HeapSafe code, and calls to free, setjmp and longjmp in non-HeapSafe code.
If the same pointer (global variable, field of a structure or array, etc) is written by HeapSafe and non-HeapSafe code, then reference counts will be corrupted:
- the pointer overwritten by the non-HeapSafe code will not have its reference count decremented, leading to inaccessible objects having greater reference counts than they should
- the object referenced by the non-HeapSafe-written code will not have its reference count incremented, possibly leading to an accessible object having a zero reference count
- if the non-HeapSafe-written pointer is subsequently overwritten by HeapSafe code, its reference count will be decremented, possibly leading to:
- a negative reference count (which will prevent deallocation)
- or, a zero reference count when there are actually remaining references
Clearly, none of these outcomes are good. HeapSafe provides two tools to detect these problems:
- at compile-time, the hs_untyped function qualifier can be used to declare functions in non-HeapSafe-compiled code which should not be passed pointers to objects containing pointers
- the debugging library's (see Debugging Mode) hsinfo function reports when HeapSafe-written pointers have been overwritten in a specific object
There are essentially three approaches to fixing these problems:
- avoid overwriting the same pointer in HeapSafe and non-HeapSafe code
- disable reference counting (using the hs_norc type qualifier) for pointers overwritten by HeapSafe and non-HeapSafe code
- switch to compiling the non-HeapSafe code with HeapSafe (if you have the source code)
Note that the following idioms do not cause major problems (aka incorrect reference counts):
- pointers to non-HeapSafe objects in non-HeapSafe code
- pointers to HeapSafe objects stored in non-HeapSafe objects - HeapSafe will however let you deallocate the reachable-from-non-HeapSafe code object
- pointers to non-HeapSafe objects in HeapSafe code - HeapSafe will even prevent deallocation of these objects while these pointers remain
Or, in other words, problems arise not from pointers between HeapSafe and non-HeapSafe objects or variables, but from pointers written by both HeapSafe and non-HeapSafe code.
Similar issues arise when non-HeapSafe-allocated objects are freed by HeapSafe code, or vice-versa. The HeapSafe library provides implementations of malloc, calloc, realloc and free so that non-HeapSafe code linked with HeapSafe code use a common memory allocation implementation. The malloc and calloc implementations behave like hs_malloc and hs_calloc respectively. But free and realloc behave like calling hs_free and hs_realloc with the adjust function argument equal to (hs_type_t)0, i.e., as if the freed object contains no pointers. This is fine as long as the objects freed by the non-HeapSafe code do not contain any pointers written by HeapSafe, but will cause problems (incorrect reference counts) otherwise. The same three approaches described above can be used to solve such problems.
HeapSafe provides its own implementation of setjmp and longjmp (to remove reference counts due to pointers in local variables when calling longjmp). These implementations work just like the standard C library ones, but use a slightly larger jmp_buf storage area. Code not compiled by HeapSafe that declares its own jmp_buf areas will not work with HeapSafe's setjmp and longjmp implementations.
In summary, HeapSafe and non-HeapSafe code can easily coexist as long as (note that these conditions are true of the standard C library, except for memcpy and friends):
- they interact only by passing non-pointer values or by sharing only objects containing non-pointers
- the non-HeapSafe code does not call setjmp and longjmp
In other cases, care must be taken to ensure that the non-HeapSafe code does not corrupt reference counts.
Three straightforward changes can improve the performance of code compiled by HeapSafe.
First, some C programs use memset (or an initialisation loop) to explicitly zero-out the memory returned by malloc. As HeapSafe's allocator explicitly zeroes-out memory, you can remove these redundant initialisations. It might also be clearer to use hs_calloc in the changed code.
Second, the cost of zeroing memory in allocation-intensive programs can be noticeable. But in fact, HeapSafe only requires that pointers be zeroed-out. If you replace calls to malloc by HS_ALLOC or HS_ARRAYALLOC, which include information on the type being allocated, HeapSafe will only zero-out pointers (in particular, no zeroing will occur if no pointers are in the allocated object). For instance:
struct large { double x[20]; struct large *next; }; void f(void) { /* Old code was ... l = malloc(sizeof(struct large)) */ struct large *l = HS_ALLOC(struct large); /* Only l->next is zeroed */ ... }
or:
char *somestr, *someoldstr; void g(void) { /* Old code was somestr = malloc(6 + strlen(someoldstr)) */ somestr = HS_ARRAYALLOC(char, 6 + strlen(someoldstr)); /* No zeroing necessary */ sprintf(somestr, "foo %s\n", someoldstr); }
The third change requires a little more effort. When HeapSafe-compiled calls a function, it saves the values of local pointer variables on a private stack, and checks this stack on deallocation attempts.[#]_ This is cheaper than performing reference count operations on writes to pointers in local variables, but can still be relatively expensive for functions that are called a lot. If a function is called a lot, but never performs any deallocation, then the work of pushing local variables is wasted.
| [6] | If HeapSafe were integrated in a C compiler (rather than working as a C-to-C compiler as today), this work could be avoided. |
If you know that a function does not deallocate objects (directly or when calling another function), then you can add an hs_nofree qualifier. This tells HeapSafe that it does not need to save local pointer variables when calling the function. Functions with the hs_nofree qualifier can only call other functions which also have the qualifier - thus adding hs_nofree to one function often requires adding it to a group of other functions.
Here's a slightly contrived example:
void add1(int *x) hs_nofree { *x++; } void addn(int *x, int n) hs_nofree { int i; for (i = 0; i < n; i++) add1(x); /* HeapSafe need not save x on this call */ } int *z; void error1(void) hs_nofree { HS_ZFREE(z); /* This will report a compile-time error, as error1 was declared nofree */ }
Many C programs include custom memory allocators, e.g., type-specific allocators, region-style allocators (e.g., Apache's pools), or malloc-like replacements. The typical motivation for these is to improve performance and/or reduce space usage.[#]_ If your program uses custom memory allocators and you want to check memory management with HeapSafe, you have several options:
- You can simply disable the custom memory allocator (at least when using HeapSafe).
- If the program uses both custom and malloc, you can modify the custom memory allocator so that pointers in the custom-deallocated objects do not prevent deallocation via free.
- (For experts only) You can extend HeapSafe's runtime library to support your custom memory allocator (and in particular, check the safety of your custom deallocations). We hope to add features to HeapSafe to make this simpler.
| [7] | Though the more malloc-like replacements sometimes fail to be better than good malloc implementations... |
For a custom allocator to interact cleanly with HeapSafe, you need to ensure three properties:
Objects allocated by the custom allocator must be returned with all pointers zeroed-out. The simplest solution here is to use memset (and not hs_memset!) to zero-out allocated objects.
When deallocating an object, the custom allocator should adjust the reference counts for pointers in the deallocated object. The custom deallocator will need to use the adjust function for the deallocated type.
The custom allocator should avoid messing up any reference counts, either by using the hs_norc type qualifier, or by compiling with:
#pragma hs_norcto disable reference counting for a whole file.
The HS_DESTROY macro makes it easy to satisfy the first two goals for type-specific memory allocators, as this simple implementation of a type-specific allocator shows:
struct T { ... the type to allocate ... }; /* T objects are actually allocated as T_allocator objects. When in the free list, the next field is "selected" and points to the next free object . When in use in the program the object field is "selected". */ union T_allocator { /* HeapSafe: do not reference count the internal allocator next pointer */ union T_allocator *hs_norc next; struct T object; } *hs_norc free_Ts; /* Note that some type-specific allocators don't use a union, instead they use various type casts. Recent C compilers (at least gcc) tend to not like such code (as in, the type-specific allocator breaks). */ void get_more_Ts(void) { ... get some extra T objects and put them on the free_Ts list ... ... HeapSafe: (pointers in the) new objects must be zeroed-out ... } struct T *alloc_T(void) { union T_allocator *allocated; /* A standard type-specific allocator sequence: get the first free object from the free list */ if (!free_Ts) get_more_Ts(); allocated = free_Ts; free_Ts = allocated->next; /* HeapSafe: zero-out the next pointer as it overlaps with some part of T */ allocated->next = NULL; return &allocated->object; } void free_T(struct T *togo) { union T_allocator *going = (union T_allocator *)togo; /* HeapSafe: zero-out the pointers in the deallocated object; note that this ensures the pointers returned by alloc_T are themselves zeroed-out */ HS_DESTROY(&going->object); going->next = free_Ts; free_Ts = going; }
The comments marked with HeapSafe: are the HeapSafe-specific changes to a typical type-specific allocator.
HeapSafe checks memory deallocations. However, it does not guarantee the safety of your C programs, for several reasons:
HeapSafe does not check type safety issues, in particular that array accesses/pointer arithmetic stay within object bounds, or that unions and void * are used correctly.
Furthermore, type safety errors can lead to erroneous reference counts, causing memory deallocation checks to go wrong (either report that a good free is bad, or that a bad free is good).
If you are concerned with type safety, you may want to check out the Deputy project.
- HeapSafe uses 8-bit reference counts (to save space). This means that HeapSafe will erroneously allow you to deallocate an object with exactly 256 (or 512, etc) references. This should be very unlikely in non-malicious code.
- If HeapSafe runs out of memory in a delayed free scope, it reverts to unchecked deallocation.
- Pointers written in non-HeapSafe code are not tracked by HeapSafe.
- Finally, uses of hs_norc allow you to disable reference-counting on a pointer-by-pointer basis.
This section presents a very brief overview of the HeapSafe implementation for single-threaded code. For a more detailed presentation and evaluation of HeapSafe, please read the HeapSafe paper.
For multi-threaded code, HeapSafe's reference counting is based on the work of Levanoni and Petrank, with modifications described in our SharC technical report.
HeapSafe associates an 8-bit reference count with each 8-byte chunk of memory, as shown in the following figure:
These 8-bit reference counts are stored in a large (512MB on a 32-bit machine) array. HeapSafe relies on Linux's on-demand page allocation strategy (a page is only reserved on the first access) to allocate only as much space as needed for this array.
As a result, the code generated by the HeapSafe compiler to update a pointer and the associated reference counts is very simple. A generic pointer write *a = b becomes (__hs_rcs is the reference count array):
if (*a) __hs_rcs[(uintptr_t)*a >> 3]--; *a = b; if (*a) __hs_rcs[(uintptr_t)*a >> 3]++;
The ifs are not necessary, but improve performance because null-pointers are very common.
HeapSafe sums all the 8-bit reference counts when checking object deallocation (see below), so pointer arithmetic does not need to update any reference counts.
As mentioned earlier, local pointer variables whose address is not taken are not reference-counted. Instead, they are saved on a private stack when a function is called. This stack is checked at deallocation time.
The other local variables containing pointers are saved to a second private stack at function entry. This stack is only used by longjmp, to remove reference counts due to local variables when unwinding the stack.
HeapSafe simply keeps a chunky list of the objects in the scope, and frees the objects (and the list) at the end of the scope. If HeapSafe runs out of memory for the chunky list, it simply performs unchecked deallocations.
At deallocation time, HeapSafe:
- calls the adjust functions for all objects being deallocated simultaneously, to remove internal pointers and pointers between deallocated objects from the reference counts
- sums the 8-bit reference counts of an object, and reports a bad free if this sum is non-zero.
- checks the private local variable stack for references to the deallocated objects and reports a bad free if any reference is found
The HeapSafe compiler is based on the CIL infrastructure. As a result, the whole compiler is by the following copyrights and licenses:
Copyright (c) 2007-2008 Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.  IN NO EVENT SHALL THE INTEL OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
and:
Copyright (c) 2001-2008, George C. Necula<EMAIL_ADDRESS>Scott McPeak<EMAIL_ADDRESS>Wes Weimer<EMAIL_ADDRESS>Ben Liblit<EMAIL_ADDRESS>Matt Harren<EMAIL_ADDRESS>Zachary Anderson<EMAIL_ADDRESS>All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.
The HeapSafe runtime library is based on version 2.8.3 of Doug Lea's public domain malloc implementation, dlmalloc. It also includes modified setjmp and longjmp functions. These are based on glibc (Linux) or Apple's libc (Mac OS X).
As a result, the HeapSafe runtime library is covered by the following licenses and copyrights:
Copyright (c) 2007 Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.  IN NO EVENT SHALL THE INTEL OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
and, for Mac OS X only:
Copyright (c) 1999-2005 Apple Computer, Inc. All rights reserved. This file contains Original Code and/or Modifications of Original Code as defined in and that are subject to the Apple Public Source License Version 2.0 (the 'License'). You may not use this file except in compliance with the License. Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ and read it before using this file.  Please see the License for the specific language governing rights and limitations under the License.
and, for Linux only:
Copyright (C) 1991-2002 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.


Full- Stack Web Developer
•Education
• HTML5
• JavaScript • jQuery
• Node.js
•(front end
framework) Foundation & Bootstrap
• Cascading Style Sheets (CSS)
• MongoDB/Mongoose
• Microsoft Office
•Trustworthy
•Reliable
• Detail-Oriented
•Teamplayer
•Flexible
My name is a Rabiah Hogans. I have a certification in full stack web development and degree in Accounting. Technology has taking precedence in all aspects of my life therefore, feeding my hunger to understand it and pursue it as a career.
When I entered this program, after deciding web development was my path, I became absolutely infatuated with the field and want to make it a life-long career.


Music Categories
Even more websites all about website templates on
Just Web Templates
Even more websites all about website templates on
Just Web Templates
Even more websites all about website templates on
Just Web Templates


Rate will change depending on the vehicle testing type:
- statuary vehicle testing is zero rated, attracting 0% VAT
- voluntary vehicle testing is standard rated, attracting 20% VAT
- retained fees are standard rated, attracting 20% VAT
{% extends "layout.html" %} {% block pageTitle %} Payment and booking information - Apply for a vehicle test or approval - GOV.UK {% endblock %} {% block beforeContent %}
Back {% endblock %} {% block content %}To book, cancel or amend an appointment, contact the Booking Section on 0300 123 900 and select option one.
Rate will change depending on the vehicle testing type:
You can pay for your test with a credit/ debit card, pre-funded account (PFA) or cheque.
To pay with a credit/ debit card:
You need to provide the operator with your:
Refer to the instructions on your application form to pay with a PFA or cheque.
Ensure you have paid for your test(s) before making a booking.
To book your test at a GVTS:
The operator will guide you through the booking process.
You must book direct with the POTF.
You can make up to three appointment changes per application. DVSA will not refund the test fee paid if you cancel your test with three working days or less notice.
You can swap like-for-like vehicle test appointments, given:
Ensure you have cancelled the GVTS booking before requesting to change to a POTF. This will make sure you are not charged for not attending the GVTS appointment.
You do not need to cancel the initial GVTS booking.
You must contact the POTF direct to change from a POTF to another test centre.
You need to be aware:


Food outlets in Oman asked to abide by rules
by Times News ServiceMuscat: In an advisory, the Regional Municipalities and Water Resources Ministry has asked all food establishments to abide by the application of Article 85 of Ministerial Decree No. 29/2016 which deals with health requirements related to public health activities.
The Ministry emphasized the need to restrict food establishments and food stores for the unavailability of a device to measure the temperature at the store.


2020 Skoda Kodiaq pricing and specs
A price rise has been combatted by extra equipment in the mid-sized Kodiaq SUV, which is still without the 140TDI variant in Australia.
by Scott Collie- shares
Skoda has added the Virtual Cockpit digital instruments to its Kodiaq seven-seat crossover, which has been given a $700 price rise for 2020.
The range is available with the existing 132TSI petrol engine, priced from $44,190 before on-road costs, and the diesel RS.
Skoda also currently offers drive-away pricing, listed at the bottom of this story.
Power in the 132TSI comes from a 2.0-litre turbocharged petrol engine making 132kW and 320Nm, mated with a seven-speed dual-clutch transmission and all-wheel drive.
Standard equipment includes a set of 19-inch alloy wheels, adaptive headlamps, leather seats, and the a suite of semi-autonomous safety assists, including autonomous emergency braking, a reversing camera, parking sensors, and adaptive cruise.
 The Virtual Cockpit, previously a $700 option, is also now standard – and explains the $700 price bump for 2020.
Skoda Kodiaq 132TSI Sportline long-termer: Interior comfort and practicality
Moving up to the Sportline doesn't add any extra power but it gets a range of sporty add-ons, including a set of 20-inch alloy wheels, a body kit, black exterior add-ons, and a set of bucket-style seats with Alcantara trim.
A range of options packages are available, including the Luxury Pack ($3700) with rear-cross traffic alert, blind-spot monitoring, a surround-view camera, and heated second-row seats.
The Tech Pack ($2900) adds a 10-speaker stereo, selectable drive modes, adaptive dampers, and hands-free parking, while a panoramic sunroof will set you back $1900, and side steps are $1300.
Finally, the range-topping Kodiaq RS. It's powered by a 2.0-litre bi-turbo-diesel engine making 176kW and 500Nm. It's also hooked up to an all-wheel drive system and a seven-speed DSG transmission.
Along with its more aggressive exterior design, the RS gets a sportier steering wheel with paddles, red stitching, and Skoda's full safety suite.
2020 Skoda Kodiaq pricing
- 132TSI - $44,190 ($47,940 drive-away)
- 132TSI Sportline - $52,190 ($52,490 drive-away)
- RS TDI - $65,990
All prices exclude on-road costs.
1
5
nextprevious
2020 Skoda Kodiaq pricing and specs